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