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