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 // UNSUPPORTED: gcc-10 12 13 // template<class I1, class I2> 14 // concept indirectly_swappable; 15 16 #include <iterator> 17 18 #include "test_macros.h" 19 20 template<class T, class ValueType = T> 21 struct PointerTo { 22 using value_type = ValueType; 23 T& operator*() const; 24 }; 25 26 static_assert(std::indirectly_swappable<PointerTo<int>>); 27 static_assert(std::indirectly_swappable<PointerTo<int>, PointerTo<int>>); 28 29 struct B; 30 31 struct A { 32 friend void iter_swap(const PointerTo<A>&, const PointerTo<A>&); 33 }; 34 35 // Is indirectly swappable. 36 struct B { 37 friend void iter_swap(const PointerTo<B>&, const PointerTo<B>&); 38 friend void iter_swap(const PointerTo<A>&, const PointerTo<B>&); 39 friend void iter_swap(const PointerTo<B>&, const PointerTo<A>&); 40 }; 41 42 // Valid except ranges::iter_swap(i2, i1). 43 struct C { 44 friend void iter_swap(const PointerTo<C>&, const PointerTo<C>&); 45 friend void iter_swap(const PointerTo<A>&, const PointerTo<C>&); 46 friend void iter_swap(const PointerTo<C>&, const PointerTo<A>&) = delete; 47 }; 48 49 // Valid except ranges::iter_swap(i1, i2). 50 struct D { 51 friend void iter_swap(const PointerTo<D>&, const PointerTo<D>&); 52 friend void iter_swap(const PointerTo<A>&, const PointerTo<D>&) = delete; 53 friend void iter_swap(const PointerTo<D>&, const PointerTo<A>&); 54 }; 55 56 // Valid except ranges::iter_swap(i2, i2). 57 struct E { 58 E operator=(const E&) = delete; 59 friend void iter_swap(const PointerTo<E>&, const PointerTo<E>&) = delete; 60 friend void iter_swap(const PointerTo<A>&, const PointerTo<E>&); 61 friend void iter_swap(const PointerTo<E>&, const PointerTo<A>&); 62 }; 63 64 struct F { 65 friend void iter_swap(const PointerTo<F>&, const PointerTo<F>&) = delete; 66 }; 67 68 // Valid except ranges::iter_swap(i1, i1). 69 struct G { 70 friend void iter_swap(const PointerTo<G>&, const PointerTo<G>&); 71 friend void iter_swap(const PointerTo<F>&, const PointerTo<G>&); 72 friend void iter_swap(const PointerTo<G>&, const PointerTo<F>&); 73 }; 74 75 76 static_assert( std::indirectly_swappable<PointerTo<A>, PointerTo<B>>); 77 static_assert(!std::indirectly_swappable<PointerTo<A>, PointerTo<C>>); 78 static_assert(!std::indirectly_swappable<PointerTo<A>, PointerTo<D>>); 79 static_assert(!std::indirectly_swappable<PointerTo<A>, PointerTo<E>>); 80 static_assert(!std::indirectly_swappable<PointerTo<A>, PointerTo<G>>); 81