1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 // UNSUPPORTED: libcpp-no-concepts 11 12 // template<class I1, class I2> 13 // concept indirectly_swappable; 14 15 #include <iterator> 16 17 #include "test_macros.h" 18 19 template<class T, class ValueType = T> 20 struct PointerTo { 21 using value_type = ValueType; 22 T& operator*() const; 23 }; 24 25 static_assert(std::indirectly_swappable<PointerTo<int>>); 26 static_assert(std::indirectly_swappable<PointerTo<int>, PointerTo<int>>); 27 28 struct B; 29 30 struct A { 31 friend void iter_swap(const PointerTo<A>&, const PointerTo<A>&); 32 }; 33 34 // Is indirectly swappable. 35 struct B { 36 friend void iter_swap(const PointerTo<B>&, const PointerTo<B>&); 37 friend void iter_swap(const PointerTo<A>&, const PointerTo<B>&); 38 friend void iter_swap(const PointerTo<B>&, const PointerTo<A>&); 39 }; 40 41 // Valid except ranges::iter_swap(i2, i1). 42 struct C { 43 friend void iter_swap(const PointerTo<C>&, const PointerTo<C>&); 44 friend void iter_swap(const PointerTo<A>&, const PointerTo<C>&); 45 friend void iter_swap(const PointerTo<C>&, const PointerTo<A>&) = delete; 46 }; 47 48 // Valid except ranges::iter_swap(i1, i2). 49 struct D { 50 friend void iter_swap(const PointerTo<D>&, const PointerTo<D>&); 51 friend void iter_swap(const PointerTo<A>&, const PointerTo<D>&) = delete; 52 friend void iter_swap(const PointerTo<D>&, const PointerTo<A>&); 53 }; 54 55 // Valid except ranges::iter_swap(i2, i2). 56 struct E { 57 E operator=(const E&) = delete; 58 friend void iter_swap(const PointerTo<E>&, const PointerTo<E>&) = delete; 59 friend void iter_swap(const PointerTo<A>&, const PointerTo<E>&); 60 friend void iter_swap(const PointerTo<E>&, const PointerTo<A>&); 61 }; 62 63 struct F { 64 friend void iter_swap(const PointerTo<F>&, const PointerTo<F>&) = delete; 65 }; 66 67 // Valid except ranges::iter_swap(i1, i1). 68 struct G { 69 friend void iter_swap(const PointerTo<G>&, const PointerTo<G>&); 70 friend void iter_swap(const PointerTo<F>&, const PointerTo<G>&); 71 friend void iter_swap(const PointerTo<G>&, const PointerTo<F>&); 72 }; 73 74 75 static_assert( std::indirectly_swappable<PointerTo<A>, PointerTo<B>>); 76 static_assert(!std::indirectly_swappable<PointerTo<A>, PointerTo<C>>); 77 static_assert(!std::indirectly_swappable<PointerTo<A>, PointerTo<D>>); 78 static_assert(!std::indirectly_swappable<PointerTo<A>, PointerTo<E>>); 79 static_assert(!std::indirectly_swappable<PointerTo<A>, PointerTo<G>>); 80