124dd2d2fSChristopher Di Bella //===----------------------------------------------------------------------===//
224dd2d2fSChristopher Di Bella //
324dd2d2fSChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
424dd2d2fSChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information.
524dd2d2fSChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
624dd2d2fSChristopher Di Bella //
724dd2d2fSChristopher Di Bella //===----------------------------------------------------------------------===//
824dd2d2fSChristopher Di Bella 
924dd2d2fSChristopher Di Bella // UNSUPPORTED: c++03, c++11, c++14, c++17
1024dd2d2fSChristopher Di Bella 
1124dd2d2fSChristopher Di Bella // template<class T, class U>
1224dd2d2fSChristopher Di Bella // concept swappable_with = // see below
1324dd2d2fSChristopher Di Bella 
1424dd2d2fSChristopher Di Bella #include <concepts>
1524dd2d2fSChristopher Di Bella 
1624dd2d2fSChristopher Di Bella #include <array>
17cedd07dfSChristopher Di Bella #include <cassert>
1824dd2d2fSChristopher Di Bella #include <deque>
1924dd2d2fSChristopher Di Bella #include <forward_list>
2024dd2d2fSChristopher Di Bella #include <list>
2124dd2d2fSChristopher Di Bella #include <map>
2224dd2d2fSChristopher Di Bella #include <memory>
2324dd2d2fSChristopher Di Bella #include <optional>
2424dd2d2fSChristopher Di Bella #include <set>
2524dd2d2fSChristopher Di Bella #include <unordered_map>
2624dd2d2fSChristopher Di Bella #include <unordered_set>
2724dd2d2fSChristopher Di Bella #include <vector>
2824dd2d2fSChristopher Di Bella 
2924dd2d2fSChristopher Di Bella #include "type_classification/moveconstructible.h"
3024dd2d2fSChristopher Di Bella #include "type_classification/swappable.h"
3124dd2d2fSChristopher Di Bella 
3224dd2d2fSChristopher Di Bella template <class T, class U>
check_swappable_with_impl()3324dd2d2fSChristopher Di Bella constexpr bool check_swappable_with_impl() {
3424dd2d2fSChristopher Di Bella   static_assert(std::swappable_with<T, U> == std::swappable_with<U, T>);
3524dd2d2fSChristopher Di Bella   return std::swappable_with<T, U>;
3624dd2d2fSChristopher Di Bella }
3724dd2d2fSChristopher Di Bella 
3824dd2d2fSChristopher Di Bella template <class T, class U>
check_swappable_with()3924dd2d2fSChristopher Di Bella constexpr bool check_swappable_with() {
4024dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T, U>());
4124dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T, U const>());
4224dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const, U>());
4324dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const, U const>());
4424dd2d2fSChristopher Di Bella 
4524dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T, U&>());
4624dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T, U const&>());
4724dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T, U volatile&>());
4824dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T, U const volatile&>());
4924dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const, U&>());
5024dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const, U const&>());
5124dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const, U volatile&>());
5224dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const, U const volatile&>());
5324dd2d2fSChristopher Di Bella 
5424dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&, U>());
5524dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&, U const>());
5624dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&, U>());
5724dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&, U const>());
5824dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&, U>());
5924dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&, U const>());
6024dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&, U>());
6124dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&, U const>());
6224dd2d2fSChristopher Di Bella 
6324dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&, U const&>());
6424dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&, U volatile&>());
6524dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&, U const volatile&>());
6624dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&, U&>());
6724dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&, U const&>());
6824dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&, U volatile&>());
6924dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&, U const volatile&>());
7024dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&, U&>());
7124dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&, U const&>());
7224dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&, U const volatile&>());
7324dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&, U&>());
7424dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&, U const&>());
7524dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&, U volatile&>());
7624dd2d2fSChristopher Di Bella   static_assert(
7724dd2d2fSChristopher Di Bella       !check_swappable_with_impl<T const volatile&, U const volatile&>());
7824dd2d2fSChristopher Di Bella 
7924dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T, U&&>());
8024dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T, U const&&>());
8124dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T, U volatile&&>());
8224dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T, U const volatile&&>());
8324dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const, U&&>());
8424dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const, U const&&>());
8524dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const, U volatile&&>());
8624dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const, U const volatile&&>());
8724dd2d2fSChristopher Di Bella 
8824dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&&, U>());
8924dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&&, U const>());
9024dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&&, U>());
9124dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&&, U const>());
9224dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&&, U>());
9324dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&&, U const>());
9424dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&&, U>());
9524dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&&, U const>());
9624dd2d2fSChristopher Di Bella 
9724dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&, U&&>());
9824dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&, U const&&>());
9924dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&, U volatile&&>());
10024dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&, U const volatile&&>());
10124dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&, U&&>());
10224dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&, U const&&>());
10324dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&, U volatile&&>());
10424dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&, U const volatile&&>());
10524dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&, U&&>());
10624dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&, U const&&>());
10724dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&, U volatile&&>());
10824dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&, U const volatile&&>());
10924dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&, U&&>());
11024dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&, U const&&>());
11124dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&, U volatile&&>());
11224dd2d2fSChristopher Di Bella   static_assert(
11324dd2d2fSChristopher Di Bella       !check_swappable_with_impl<T const volatile&, U const volatile&&>());
11424dd2d2fSChristopher Di Bella 
11524dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&&, U&>());
11624dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&&, U const&>());
11724dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&&, U volatile&>());
11824dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&&, U const volatile&>());
11924dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&&, U&>());
12024dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&&, U const&>());
12124dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&&, U volatile&>());
12224dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&&, U const volatile&>());
12324dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&&, U&>());
12424dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&&, U const&>());
12524dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&&, U volatile&>());
12624dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&&, U const volatile&>());
12724dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&&, U&>());
12824dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&&, U const&>());
12924dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&&, U volatile&>());
13024dd2d2fSChristopher Di Bella   static_assert(
13124dd2d2fSChristopher Di Bella       !check_swappable_with_impl<T const volatile&&, U const volatile&>());
13224dd2d2fSChristopher Di Bella 
13324dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&&, U&&>());
13424dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&&, U const&&>());
13524dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&&, U volatile&&>());
13624dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T&&, U const volatile&&>());
13724dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&&, U&&>());
13824dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&&, U const&&>());
13924dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&&, U volatile&&>());
14024dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const&&, U const volatile&&>());
14124dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&&, U&&>());
14224dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&&, U const&&>());
14324dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&&, U volatile&&>());
14424dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T volatile&&, U const volatile&&>());
14524dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&&, U&&>());
14624dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&&, U const&&>());
14724dd2d2fSChristopher Di Bella   static_assert(!check_swappable_with_impl<T const volatile&&, U volatile&&>());
14824dd2d2fSChristopher Di Bella   static_assert(
14924dd2d2fSChristopher Di Bella       !check_swappable_with_impl<T const volatile&&, U const volatile&&>());
15024dd2d2fSChristopher Di Bella   return check_swappable_with_impl<T&, U&>();
15124dd2d2fSChristopher Di Bella }
15224dd2d2fSChristopher Di Bella 
15324dd2d2fSChristopher Di Bella template <class T, class U>
check_swappable_with_including_lvalue_ref_to_volatile()15424dd2d2fSChristopher Di Bella constexpr bool check_swappable_with_including_lvalue_ref_to_volatile() {
15524dd2d2fSChristopher Di Bella   constexpr auto result = check_swappable_with<T, U>();
15624dd2d2fSChristopher Di Bella   static_assert(check_swappable_with_impl<T volatile&, U volatile&>() ==
15724dd2d2fSChristopher Di Bella                 result);
15824dd2d2fSChristopher Di Bella   return result;
15924dd2d2fSChristopher Di Bella }
16024dd2d2fSChristopher Di Bella 
16124dd2d2fSChristopher Di Bella namespace fundamental {
16224dd2d2fSChristopher Di Bella static_assert(
16324dd2d2fSChristopher Di Bella     check_swappable_with_including_lvalue_ref_to_volatile<int, int>());
16424dd2d2fSChristopher Di Bella static_assert(
16524dd2d2fSChristopher Di Bella     check_swappable_with_including_lvalue_ref_to_volatile<double, double>());
16624dd2d2fSChristopher Di Bella static_assert(
16724dd2d2fSChristopher Di Bella     !check_swappable_with_including_lvalue_ref_to_volatile<int, double>());
16824dd2d2fSChristopher Di Bella 
16924dd2d2fSChristopher Di Bella static_assert(
17024dd2d2fSChristopher Di Bella     check_swappable_with_including_lvalue_ref_to_volatile<int*, int*>());
17124dd2d2fSChristopher Di Bella static_assert(
17224dd2d2fSChristopher Di Bella     !check_swappable_with_including_lvalue_ref_to_volatile<int, int*>());
17324dd2d2fSChristopher Di Bella static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
17424dd2d2fSChristopher Di Bella               int (*)(), int (*)()>());
17524dd2d2fSChristopher Di Bella static_assert(
17624dd2d2fSChristopher Di Bella     !check_swappable_with_including_lvalue_ref_to_volatile<int, int (*)()>());
17724dd2d2fSChristopher Di Bella 
17824dd2d2fSChristopher Di Bella struct S {};
17924dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<int, S>());
18024dd2d2fSChristopher Di Bella static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
18124dd2d2fSChristopher Di Bella               int S::*, int S::*>());
18224dd2d2fSChristopher Di Bella static_assert(
18324dd2d2fSChristopher Di Bella     !check_swappable_with_including_lvalue_ref_to_volatile<int, int S::*>());
18424dd2d2fSChristopher Di Bella static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
18524dd2d2fSChristopher Di Bella               int (S::*)(), int (S::*)()>());
18624dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
18724dd2d2fSChristopher Di Bella               int, int (S::*)()>());
18824dd2d2fSChristopher Di Bella static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
18924dd2d2fSChristopher Di Bella               int (S::*)() noexcept, int (S::*)() noexcept>());
19024dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
19124dd2d2fSChristopher Di Bella               int (S::*)() noexcept, int (S::*)()>());
19224dd2d2fSChristopher Di Bella static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
19324dd2d2fSChristopher Di Bella               int (S::*)() const, int (S::*)() const>());
19424dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
19524dd2d2fSChristopher Di Bella               int (S::*)() const, int (S::*)()>());
19624dd2d2fSChristopher Di Bella static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
19724dd2d2fSChristopher Di Bella               int (S::*)() const noexcept, int (S::*)() const noexcept>());
19824dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
19924dd2d2fSChristopher Di Bella               int (S::*)() const, int (S::*)() const noexcept>());
20024dd2d2fSChristopher Di Bella static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
20124dd2d2fSChristopher Di Bella               int (S::*)() volatile, int (S::*)() volatile>());
20224dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
20324dd2d2fSChristopher Di Bella               int (S::*)() volatile, int (S::*)()>());
20424dd2d2fSChristopher Di Bella static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
20524dd2d2fSChristopher Di Bella               int (S::*)() const volatile, int (S::*)() const volatile>());
20624dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
20724dd2d2fSChristopher Di Bella               int (S::*)() const volatile, int (S::*)()>());
20824dd2d2fSChristopher Di Bella 
20924dd2d2fSChristopher Di Bella static_assert(
21024dd2d2fSChristopher Di Bella     check_swappable_with_including_lvalue_ref_to_volatile<int[5], int[5]>());
21124dd2d2fSChristopher Di Bella static_assert(
21224dd2d2fSChristopher Di Bella     !check_swappable_with_including_lvalue_ref_to_volatile<int[5], int[6]>());
21324dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
21424dd2d2fSChristopher Di Bella               int[5], double[5]>());
21524dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
21624dd2d2fSChristopher Di Bella               int[5], double[6]>());
21724dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<int[5][6],
21824dd2d2fSChristopher Di Bella                                                                      int[5]>());
21924dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<int[5][6],
22024dd2d2fSChristopher Di Bella                                                                      int[6]>());
22124dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
22224dd2d2fSChristopher Di Bella               int[5][6], double[5]>());
22324dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
22424dd2d2fSChristopher Di Bella               int[5][6], double[6]>());
22524dd2d2fSChristopher Di Bella static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
22624dd2d2fSChristopher Di Bella               int[5][6], int[5][6]>());
22724dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
22824dd2d2fSChristopher Di Bella               int[5][6], int[5][4]>());
22924dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
23024dd2d2fSChristopher Di Bella               int[5][6], int[6][5]>());
23124dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
23224dd2d2fSChristopher Di Bella               int[5][6], double[5][6]>());
23324dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
23424dd2d2fSChristopher Di Bella               int[5][6], double[6][5]>());
23524dd2d2fSChristopher Di Bella 
23624dd2d2fSChristopher Di Bella // always false
23724dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_impl<void, void>());
23824dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_impl<int, void>());
23924dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_impl<int&, void>());
24024dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_impl<void, int>());
24124dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_impl<void, int&>());
24224dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_impl<int, int()>());
24324dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_impl<int, int (&)()>());
24424dd2d2fSChristopher Di Bella } // namespace fundamental
24524dd2d2fSChristopher Di Bella 
24624dd2d2fSChristopher Di Bella namespace adl {
24724dd2d2fSChristopher Di Bella static_assert(
24824dd2d2fSChristopher Di Bella     check_swappable_with<lvalue_adl_swappable, lvalue_adl_swappable>());
24924dd2d2fSChristopher Di Bella static_assert(check_swappable_with<lvalue_rvalue_adl_swappable,
25024dd2d2fSChristopher Di Bella                                    lvalue_rvalue_adl_swappable>());
25124dd2d2fSChristopher Di Bella static_assert(check_swappable_with<rvalue_lvalue_adl_swappable,
25224dd2d2fSChristopher Di Bella                                    rvalue_lvalue_adl_swappable>());
25324dd2d2fSChristopher Di Bella static_assert(
25424dd2d2fSChristopher Di Bella     check_swappable_with_impl<rvalue_adl_swappable, rvalue_adl_swappable>());
25524dd2d2fSChristopher Di Bella static_assert(!check_swappable_with_impl<lvalue_rvalue_adl_swappable&,
25624dd2d2fSChristopher Di Bella                                          lvalue_rvalue_adl_swappable&&>());
25724dd2d2fSChristopher Di Bella 
25824dd2d2fSChristopher Di Bella struct s1 {};
25924dd2d2fSChristopher Di Bella struct no_common_reference_with_s1 {
26024dd2d2fSChristopher Di Bella   friend void swap(s1&, no_common_reference_with_s1&);
26124dd2d2fSChristopher Di Bella   friend void swap(no_common_reference_with_s1&, s1&);
26224dd2d2fSChristopher Di Bella };
26324dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<s1, no_common_reference_with_s1>());
26424dd2d2fSChristopher Di Bella 
26524dd2d2fSChristopher Di Bella struct one_way_swappable_with_s1 {
26624dd2d2fSChristopher Di Bella   friend void swap(s1&, one_way_swappable_with_s1&);
26724dd2d2fSChristopher Di Bella   operator s1();
26824dd2d2fSChristopher Di Bella };
26924dd2d2fSChristopher Di Bella static_assert(std::common_reference_with<one_way_swappable_with_s1, s1>);
27024dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<one_way_swappable_with_s1, s1>());
27124dd2d2fSChristopher Di Bella 
27224dd2d2fSChristopher Di Bella struct one_way_swappable_with_s1_other_way {
27324dd2d2fSChristopher Di Bella   friend void swap(one_way_swappable_with_s1_other_way&, s1&);
27424dd2d2fSChristopher Di Bella   operator s1();
27524dd2d2fSChristopher Di Bella };
27624dd2d2fSChristopher Di Bella static_assert(
27724dd2d2fSChristopher Di Bella     std::common_reference_with<one_way_swappable_with_s1_other_way, s1>);
27824dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<one_way_swappable_with_s1_other_way, s1>());
27924dd2d2fSChristopher Di Bella 
28024dd2d2fSChristopher Di Bella struct can_swap_with_s1_but_not_swappable {
28124dd2d2fSChristopher Di Bella   can_swap_with_s1_but_not_swappable(can_swap_with_s1_but_not_swappable&&) =
28224dd2d2fSChristopher Di Bella       delete;
28324dd2d2fSChristopher Di Bella   friend void swap(s1&, can_swap_with_s1_but_not_swappable&);
28424dd2d2fSChristopher Di Bella   friend void swap(can_swap_with_s1_but_not_swappable&, s1&);
28524dd2d2fSChristopher Di Bella 
28624dd2d2fSChristopher Di Bella   operator s1() const;
28724dd2d2fSChristopher Di Bella };
28824dd2d2fSChristopher Di Bella static_assert(
28924dd2d2fSChristopher Di Bella     std::common_reference_with<can_swap_with_s1_but_not_swappable, s1>);
29024dd2d2fSChristopher Di Bella static_assert(!std::swappable<can_swap_with_s1_but_not_swappable>);
29124dd2d2fSChristopher Di Bella static_assert(
29224dd2d2fSChristopher Di Bella     !check_swappable_with<can_swap_with_s1_but_not_swappable&, s1&>());
29324dd2d2fSChristopher Di Bella 
29424dd2d2fSChristopher Di Bella struct swappable_with_s1 {
29524dd2d2fSChristopher Di Bella   friend void swap(s1&, swappable_with_s1&);
29624dd2d2fSChristopher Di Bella   friend void swap(swappable_with_s1&, s1&);
29724dd2d2fSChristopher Di Bella   operator s1() const;
29824dd2d2fSChristopher Di Bella };
29924dd2d2fSChristopher Di Bella static_assert(check_swappable_with<swappable_with_s1, s1>());
30024dd2d2fSChristopher Di Bella 
30124dd2d2fSChristopher Di Bella struct swappable_with_const_s1_but_not_swappable {
30224dd2d2fSChristopher Di Bella   swappable_with_const_s1_but_not_swappable(
30324dd2d2fSChristopher Di Bella       swappable_with_const_s1_but_not_swappable const&);
30424dd2d2fSChristopher Di Bella   swappable_with_const_s1_but_not_swappable(
30524dd2d2fSChristopher Di Bella       swappable_with_const_s1_but_not_swappable const&&);
30624dd2d2fSChristopher Di Bella   swappable_with_const_s1_but_not_swappable&
30724dd2d2fSChristopher Di Bella   operator=(swappable_with_const_s1_but_not_swappable const&);
30824dd2d2fSChristopher Di Bella   swappable_with_const_s1_but_not_swappable&
30924dd2d2fSChristopher Di Bella   operator=(swappable_with_const_s1_but_not_swappable const&&);
31024dd2d2fSChristopher Di Bella 
31124dd2d2fSChristopher Di Bella   friend void swap(s1 const&, swappable_with_const_s1_but_not_swappable const&);
31224dd2d2fSChristopher Di Bella   friend void swap(swappable_with_const_s1_but_not_swappable const&, s1 const&);
31324dd2d2fSChristopher Di Bella 
31424dd2d2fSChristopher Di Bella   operator s1 const &() const;
31524dd2d2fSChristopher Di Bella };
31624dd2d2fSChristopher Di Bella static_assert(
31724dd2d2fSChristopher Di Bella     !std::swappable<swappable_with_const_s1_but_not_swappable const&>);
31824dd2d2fSChristopher Di Bella static_assert(!std::swappable_with<
31924dd2d2fSChristopher Di Bella               swappable_with_const_s1_but_not_swappable const&, s1 const&>);
32024dd2d2fSChristopher Di Bella 
32124dd2d2fSChristopher Di Bella struct swappable_with_volatile_s1_but_not_swappable {
32224dd2d2fSChristopher Di Bella   swappable_with_volatile_s1_but_not_swappable(
32324dd2d2fSChristopher Di Bella       swappable_with_volatile_s1_but_not_swappable volatile&);
32424dd2d2fSChristopher Di Bella   swappable_with_volatile_s1_but_not_swappable(
32524dd2d2fSChristopher Di Bella       swappable_with_volatile_s1_but_not_swappable volatile&&);
32624dd2d2fSChristopher Di Bella   swappable_with_volatile_s1_but_not_swappable&
32724dd2d2fSChristopher Di Bella   operator=(swappable_with_volatile_s1_but_not_swappable volatile&);
32824dd2d2fSChristopher Di Bella   swappable_with_volatile_s1_but_not_swappable&
32924dd2d2fSChristopher Di Bella   operator=(swappable_with_volatile_s1_but_not_swappable volatile&&);
33024dd2d2fSChristopher Di Bella 
33124dd2d2fSChristopher Di Bella   friend void swap(s1 volatile&,
33224dd2d2fSChristopher Di Bella                    swappable_with_volatile_s1_but_not_swappable volatile&);
33324dd2d2fSChristopher Di Bella   friend void swap(swappable_with_volatile_s1_but_not_swappable volatile&,
33424dd2d2fSChristopher Di Bella                    s1 volatile&);
33524dd2d2fSChristopher Di Bella 
33624dd2d2fSChristopher Di Bella   operator s1 volatile &() volatile;
33724dd2d2fSChristopher Di Bella };
33824dd2d2fSChristopher Di Bella static_assert(
33924dd2d2fSChristopher Di Bella     !std::swappable<swappable_with_volatile_s1_but_not_swappable volatile&>);
34024dd2d2fSChristopher Di Bella static_assert(
34124dd2d2fSChristopher Di Bella     !std::swappable_with<swappable_with_volatile_s1_but_not_swappable volatile&,
34224dd2d2fSChristopher Di Bella                          s1 volatile&>);
34324dd2d2fSChristopher Di Bella 
34424dd2d2fSChristopher Di Bella struct swappable_with_cv_s1_but_not_swappable {
34524dd2d2fSChristopher Di Bella   swappable_with_cv_s1_but_not_swappable(
34624dd2d2fSChristopher Di Bella       swappable_with_cv_s1_but_not_swappable const volatile&);
34724dd2d2fSChristopher Di Bella   swappable_with_cv_s1_but_not_swappable(
34824dd2d2fSChristopher Di Bella       swappable_with_cv_s1_but_not_swappable const volatile&&);
34924dd2d2fSChristopher Di Bella   swappable_with_cv_s1_but_not_swappable&
35024dd2d2fSChristopher Di Bella   operator=(swappable_with_cv_s1_but_not_swappable const volatile&);
35124dd2d2fSChristopher Di Bella   swappable_with_cv_s1_but_not_swappable&
35224dd2d2fSChristopher Di Bella   operator=(swappable_with_cv_s1_but_not_swappable const volatile&&);
35324dd2d2fSChristopher Di Bella 
35424dd2d2fSChristopher Di Bella   friend void swap(s1 const volatile&,
35524dd2d2fSChristopher Di Bella                    swappable_with_cv_s1_but_not_swappable const volatile&);
35624dd2d2fSChristopher Di Bella   friend void swap(swappable_with_cv_s1_but_not_swappable const volatile&,
35724dd2d2fSChristopher Di Bella                    s1 const volatile&);
35824dd2d2fSChristopher Di Bella 
35924dd2d2fSChristopher Di Bella   operator s1 const volatile &() const volatile;
36024dd2d2fSChristopher Di Bella };
36124dd2d2fSChristopher Di Bella static_assert(
36224dd2d2fSChristopher Di Bella     !std::swappable<swappable_with_cv_s1_but_not_swappable const volatile&>);
36324dd2d2fSChristopher Di Bella static_assert(
36424dd2d2fSChristopher Di Bella     !std::swappable_with<swappable_with_cv_s1_but_not_swappable const volatile&,
36524dd2d2fSChristopher Di Bella                          s1 const volatile&>);
36624dd2d2fSChristopher Di Bella 
36724dd2d2fSChristopher Di Bella struct s2 {
36824dd2d2fSChristopher Di Bella   friend void swap(s2 const&, s2 const&);
36924dd2d2fSChristopher Di Bella   friend void swap(s2 volatile&, s2 volatile&);
37024dd2d2fSChristopher Di Bella   friend void swap(s2 const volatile&, s2 const volatile&);
37124dd2d2fSChristopher Di Bella };
37224dd2d2fSChristopher Di Bella 
37324dd2d2fSChristopher Di Bella struct swappable_with_const_s2 {
37424dd2d2fSChristopher Di Bella   swappable_with_const_s2(swappable_with_const_s2 const&);
37524dd2d2fSChristopher Di Bella   swappable_with_const_s2(swappable_with_const_s2 const&&);
37624dd2d2fSChristopher Di Bella   swappable_with_const_s2& operator=(swappable_with_const_s2 const&);
37724dd2d2fSChristopher Di Bella   swappable_with_const_s2& operator=(swappable_with_const_s2 const&&);
37824dd2d2fSChristopher Di Bella 
37924dd2d2fSChristopher Di Bella   friend void swap(swappable_with_const_s2 const&,
38024dd2d2fSChristopher Di Bella                    swappable_with_const_s2 const&);
38124dd2d2fSChristopher Di Bella   friend void swap(s2 const&, swappable_with_const_s2 const&);
38224dd2d2fSChristopher Di Bella   friend void swap(swappable_with_const_s2 const&, s2 const&);
38324dd2d2fSChristopher Di Bella 
38424dd2d2fSChristopher Di Bella   operator s2 const &() const;
38524dd2d2fSChristopher Di Bella };
38624dd2d2fSChristopher Di Bella static_assert(std::swappable_with<swappable_with_const_s2 const&, s2 const&>);
38724dd2d2fSChristopher Di Bella 
38824dd2d2fSChristopher Di Bella struct swappable_with_volatile_s2 {
38924dd2d2fSChristopher Di Bella   swappable_with_volatile_s2(swappable_with_volatile_s2 volatile&);
39024dd2d2fSChristopher Di Bella   swappable_with_volatile_s2(swappable_with_volatile_s2 volatile&&);
39124dd2d2fSChristopher Di Bella   swappable_with_volatile_s2& operator=(swappable_with_volatile_s2 volatile&);
39224dd2d2fSChristopher Di Bella   swappable_with_volatile_s2& operator=(swappable_with_volatile_s2 volatile&&);
39324dd2d2fSChristopher Di Bella 
39424dd2d2fSChristopher Di Bella   friend void swap(swappable_with_volatile_s2 volatile&,
39524dd2d2fSChristopher Di Bella                    swappable_with_volatile_s2 volatile&);
39624dd2d2fSChristopher Di Bella   friend void swap(s2 volatile&, swappable_with_volatile_s2 volatile&);
39724dd2d2fSChristopher Di Bella   friend void swap(swappable_with_volatile_s2 volatile&, s2 volatile&);
39824dd2d2fSChristopher Di Bella 
39924dd2d2fSChristopher Di Bella   operator s2 volatile &() volatile;
40024dd2d2fSChristopher Di Bella };
40124dd2d2fSChristopher Di Bella static_assert(
40224dd2d2fSChristopher Di Bella     std::swappable_with<swappable_with_volatile_s2 volatile&, s2 volatile&>);
40324dd2d2fSChristopher Di Bella 
40424dd2d2fSChristopher Di Bella struct swappable_with_cv_s2 {
40524dd2d2fSChristopher Di Bella   swappable_with_cv_s2(swappable_with_cv_s2 const volatile&);
40624dd2d2fSChristopher Di Bella   swappable_with_cv_s2(swappable_with_cv_s2 const volatile&&);
40724dd2d2fSChristopher Di Bella   swappable_with_cv_s2& operator=(swappable_with_cv_s2 const volatile&);
40824dd2d2fSChristopher Di Bella   swappable_with_cv_s2& operator=(swappable_with_cv_s2 const volatile&&);
40924dd2d2fSChristopher Di Bella 
41024dd2d2fSChristopher Di Bella   friend void swap(swappable_with_cv_s2 const volatile&,
41124dd2d2fSChristopher Di Bella                    swappable_with_cv_s2 const volatile&);
41224dd2d2fSChristopher Di Bella   friend void swap(s2 const volatile&, swappable_with_cv_s2 const volatile&);
41324dd2d2fSChristopher Di Bella   friend void swap(swappable_with_cv_s2 const volatile&, s2 const volatile&);
41424dd2d2fSChristopher Di Bella 
41524dd2d2fSChristopher Di Bella   operator s2 const volatile &() const volatile;
41624dd2d2fSChristopher Di Bella };
41724dd2d2fSChristopher Di Bella static_assert(std::swappable_with<swappable_with_cv_s2 const volatile&,
41824dd2d2fSChristopher Di Bella                                   s2 const volatile&>);
41924dd2d2fSChristopher Di Bella 
42024dd2d2fSChristopher Di Bella struct swappable_with_rvalue_ref_to_s1_but_not_swappable {
42124dd2d2fSChristopher Di Bella   friend void swap(swappable_with_rvalue_ref_to_s1_but_not_swappable&&,
42224dd2d2fSChristopher Di Bella                    swappable_with_rvalue_ref_to_s1_but_not_swappable&&);
42324dd2d2fSChristopher Di Bella   friend void swap(s1&&, swappable_with_rvalue_ref_to_s1_but_not_swappable&&);
42424dd2d2fSChristopher Di Bella   friend void swap(swappable_with_rvalue_ref_to_s1_but_not_swappable&&, s1&&);
42524dd2d2fSChristopher Di Bella 
42624dd2d2fSChristopher Di Bella   operator s1() const;
42724dd2d2fSChristopher Di Bella };
42824dd2d2fSChristopher Di Bella static_assert(
42924dd2d2fSChristopher Di Bella     !std::swappable<swappable_with_rvalue_ref_to_s1_but_not_swappable const&&>);
43024dd2d2fSChristopher Di Bella static_assert(
43124dd2d2fSChristopher Di Bella     !std::swappable_with<
43224dd2d2fSChristopher Di Bella         swappable_with_rvalue_ref_to_s1_but_not_swappable const&&, s1 const&&>);
43324dd2d2fSChristopher Di Bella 
43424dd2d2fSChristopher Di Bella struct swappable_with_rvalue_ref_to_const_s1_but_not_swappable {
43524dd2d2fSChristopher Di Bella   friend void
43624dd2d2fSChristopher Di Bella   swap(s1 const&&,
43724dd2d2fSChristopher Di Bella        swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&);
43824dd2d2fSChristopher Di Bella   friend void
43924dd2d2fSChristopher Di Bella   swap(swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&,
44024dd2d2fSChristopher Di Bella        s1 const&&);
44124dd2d2fSChristopher Di Bella 
44224dd2d2fSChristopher Di Bella   operator s1 const() const;
44324dd2d2fSChristopher Di Bella };
44424dd2d2fSChristopher Di Bella static_assert(!std::swappable<
44524dd2d2fSChristopher Di Bella               swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&>);
44624dd2d2fSChristopher Di Bella static_assert(!std::swappable_with<
44724dd2d2fSChristopher Di Bella               swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&,
44824dd2d2fSChristopher Di Bella               s1 const&&>);
44924dd2d2fSChristopher Di Bella 
45024dd2d2fSChristopher Di Bella struct swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable {
45124dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable(
45224dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&);
45324dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable(
45424dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&);
45524dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable& operator=(
45624dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&);
45724dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable& operator=(
45824dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&);
45924dd2d2fSChristopher Di Bella 
46024dd2d2fSChristopher Di Bella   friend void
46124dd2d2fSChristopher Di Bella   swap(s1 volatile&&,
46224dd2d2fSChristopher Di Bella        swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&);
46324dd2d2fSChristopher Di Bella   friend void
46424dd2d2fSChristopher Di Bella   swap(swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&,
46524dd2d2fSChristopher Di Bella        s1 volatile&&);
46624dd2d2fSChristopher Di Bella 
46724dd2d2fSChristopher Di Bella   operator s1 volatile &&() volatile&&;
46824dd2d2fSChristopher Di Bella };
46924dd2d2fSChristopher Di Bella static_assert(
47024dd2d2fSChristopher Di Bella     !std::swappable<
47124dd2d2fSChristopher Di Bella         swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&>);
47224dd2d2fSChristopher Di Bella static_assert(
47324dd2d2fSChristopher Di Bella     !std::swappable_with<
47424dd2d2fSChristopher Di Bella         swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&,
47524dd2d2fSChristopher Di Bella         s1 volatile&&>);
47624dd2d2fSChristopher Di Bella 
47724dd2d2fSChristopher Di Bella struct swappable_with_rvalue_ref_to_cv_s1_but_not_swappable {
47824dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_cv_s1_but_not_swappable(
47924dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&);
48024dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_cv_s1_but_not_swappable(
48124dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&);
48224dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_cv_s1_but_not_swappable& operator=(
48324dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&);
48424dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_cv_s1_but_not_swappable& operator=(
48524dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&);
48624dd2d2fSChristopher Di Bella 
48724dd2d2fSChristopher Di Bella   friend void
48824dd2d2fSChristopher Di Bella   swap(s1 const volatile&&,
48924dd2d2fSChristopher Di Bella        swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&);
49024dd2d2fSChristopher Di Bella   friend void
49124dd2d2fSChristopher Di Bella   swap(swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&,
49224dd2d2fSChristopher Di Bella        s1 const volatile&&);
49324dd2d2fSChristopher Di Bella 
49424dd2d2fSChristopher Di Bella   operator s1 const volatile &&() const volatile&&;
49524dd2d2fSChristopher Di Bella };
49624dd2d2fSChristopher Di Bella static_assert(
49724dd2d2fSChristopher Di Bella     !std::swappable<
49824dd2d2fSChristopher Di Bella         swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&>);
49924dd2d2fSChristopher Di Bella static_assert(
50024dd2d2fSChristopher Di Bella     !std::swappable_with<
50124dd2d2fSChristopher Di Bella         swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&,
50224dd2d2fSChristopher Di Bella         s1 const volatile&&>);
50324dd2d2fSChristopher Di Bella 
50424dd2d2fSChristopher Di Bella struct s3 {
50524dd2d2fSChristopher Di Bella   friend void swap(s3&&, s3&&);
50624dd2d2fSChristopher Di Bella   friend void swap(s3 const&&, s3 const&&);
50724dd2d2fSChristopher Di Bella   friend void swap(s3 volatile&&, s3 volatile&&);
50824dd2d2fSChristopher Di Bella   friend void swap(s3 const volatile&&, s3 const volatile&&);
50924dd2d2fSChristopher Di Bella };
51024dd2d2fSChristopher Di Bella 
51124dd2d2fSChristopher Di Bella struct swappable_with_rvalue_ref_to_s3 {
51224dd2d2fSChristopher Di Bella   friend void swap(swappable_with_rvalue_ref_to_s3&&,
51324dd2d2fSChristopher Di Bella                    swappable_with_rvalue_ref_to_s3&&);
51424dd2d2fSChristopher Di Bella   friend void swap(s3&&, swappable_with_rvalue_ref_to_s3&&);
51524dd2d2fSChristopher Di Bella   friend void swap(swappable_with_rvalue_ref_to_s3&&, s3&&);
51624dd2d2fSChristopher Di Bella 
51724dd2d2fSChristopher Di Bella   operator s3() const;
51824dd2d2fSChristopher Di Bella };
51924dd2d2fSChristopher Di Bella static_assert(std::swappable_with<swappable_with_rvalue_ref_to_s3&&, s3&&>);
52024dd2d2fSChristopher Di Bella 
52124dd2d2fSChristopher Di Bella struct swappable_with_rvalue_ref_to_const_s3 {
52224dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_const_s3(
52324dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_const_s3 const&);
52424dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_const_s3(
52524dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_const_s3 const&&);
52624dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_const_s3&
52724dd2d2fSChristopher Di Bella   operator=(swappable_with_rvalue_ref_to_const_s3 const&);
52824dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_const_s3&
52924dd2d2fSChristopher Di Bella   operator=(swappable_with_rvalue_ref_to_const_s3 const&&);
53024dd2d2fSChristopher Di Bella 
53124dd2d2fSChristopher Di Bella   friend void swap(swappable_with_rvalue_ref_to_const_s3 const&&,
53224dd2d2fSChristopher Di Bella                    swappable_with_rvalue_ref_to_const_s3 const&&);
53324dd2d2fSChristopher Di Bella   friend void swap(s3 const&&, swappable_with_rvalue_ref_to_const_s3 const&&);
53424dd2d2fSChristopher Di Bella   friend void swap(swappable_with_rvalue_ref_to_const_s3 const&&, s3 const&&);
53524dd2d2fSChristopher Di Bella 
53624dd2d2fSChristopher Di Bella   operator s3() const;
53724dd2d2fSChristopher Di Bella };
53824dd2d2fSChristopher Di Bella static_assert(std::swappable_with<swappable_with_rvalue_ref_to_const_s3 const&&,
53924dd2d2fSChristopher Di Bella                                   s3 const&&>);
54024dd2d2fSChristopher Di Bella 
54124dd2d2fSChristopher Di Bella struct swappable_with_rvalue_ref_to_volatile_s3 {
54224dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_volatile_s3(
54324dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_volatile_s3 volatile&);
54424dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_volatile_s3(
54524dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
54624dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_volatile_s3&
54724dd2d2fSChristopher Di Bella   operator=(swappable_with_rvalue_ref_to_volatile_s3 volatile&);
54824dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_volatile_s3&
54924dd2d2fSChristopher Di Bella   operator=(swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
55024dd2d2fSChristopher Di Bella 
55124dd2d2fSChristopher Di Bella   friend void swap(swappable_with_rvalue_ref_to_volatile_s3 volatile&&,
55224dd2d2fSChristopher Di Bella                    swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
55324dd2d2fSChristopher Di Bella   friend void swap(s3 volatile&&,
55424dd2d2fSChristopher Di Bella                    swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
55524dd2d2fSChristopher Di Bella   friend void swap(swappable_with_rvalue_ref_to_volatile_s3 volatile&&,
55624dd2d2fSChristopher Di Bella                    s3 volatile&&);
55724dd2d2fSChristopher Di Bella 
558cedd07dfSChristopher Di Bella   operator s3 volatile &&() volatile;
55924dd2d2fSChristopher Di Bella };
56024dd2d2fSChristopher Di Bella static_assert(
56124dd2d2fSChristopher Di Bella     std::swappable_with<swappable_with_rvalue_ref_to_volatile_s3 volatile&&,
56224dd2d2fSChristopher Di Bella                         s3 volatile&&>);
56324dd2d2fSChristopher Di Bella 
56424dd2d2fSChristopher Di Bella struct swappable_with_rvalue_ref_to_cv_s3 {
56524dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_cv_s3(
56624dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_cv_s3 const volatile&);
56724dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_cv_s3(
56824dd2d2fSChristopher Di Bella       swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
56924dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_cv_s3&
57024dd2d2fSChristopher Di Bella   operator=(swappable_with_rvalue_ref_to_cv_s3 const volatile&);
57124dd2d2fSChristopher Di Bella   swappable_with_rvalue_ref_to_cv_s3&
57224dd2d2fSChristopher Di Bella   operator=(swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
57324dd2d2fSChristopher Di Bella 
57424dd2d2fSChristopher Di Bella   friend void swap(swappable_with_rvalue_ref_to_cv_s3 const volatile&&,
57524dd2d2fSChristopher Di Bella                    swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
57624dd2d2fSChristopher Di Bella   friend void swap(s3 const volatile&&,
57724dd2d2fSChristopher Di Bella                    swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
57824dd2d2fSChristopher Di Bella   friend void swap(swappable_with_rvalue_ref_to_cv_s3 const volatile&&,
57924dd2d2fSChristopher Di Bella                    s3 const volatile&&);
58024dd2d2fSChristopher Di Bella 
581cedd07dfSChristopher Di Bella   operator s3 const volatile &&() const volatile;
58224dd2d2fSChristopher Di Bella };
58324dd2d2fSChristopher Di Bella static_assert(
58424dd2d2fSChristopher Di Bella     std::swappable_with<swappable_with_rvalue_ref_to_cv_s3 const volatile&&,
58524dd2d2fSChristopher Di Bella                         s3 const volatile&&>);
58624dd2d2fSChristopher Di Bella 
58724dd2d2fSChristopher Di Bella namespace union_swap {
58824dd2d2fSChristopher Di Bella union adl_swappable {
58924dd2d2fSChristopher Di Bella   int x;
59024dd2d2fSChristopher Di Bella   double y;
59124dd2d2fSChristopher Di Bella 
59224dd2d2fSChristopher Di Bella   operator int() const;
59324dd2d2fSChristopher Di Bella };
59424dd2d2fSChristopher Di Bella 
59524dd2d2fSChristopher Di Bella void swap(adl_swappable&, adl_swappable&) noexcept;
59624dd2d2fSChristopher Di Bella void swap(adl_swappable&&, adl_swappable&&) noexcept;
59724dd2d2fSChristopher Di Bella void swap(adl_swappable&, int&) noexcept;
59824dd2d2fSChristopher Di Bella void swap(int&, adl_swappable&) noexcept;
59924dd2d2fSChristopher Di Bella } // namespace union_swap
60024dd2d2fSChristopher Di Bella static_assert(
60124dd2d2fSChristopher Di Bella     std::swappable_with<union_swap::adl_swappable, union_swap::adl_swappable>);
60224dd2d2fSChristopher Di Bella static_assert(std::swappable_with<union_swap::adl_swappable&,
60324dd2d2fSChristopher Di Bella                                   union_swap::adl_swappable&>);
60424dd2d2fSChristopher Di Bella static_assert(std::swappable_with<union_swap::adl_swappable&&,
60524dd2d2fSChristopher Di Bella                                   union_swap::adl_swappable&&>);
60624dd2d2fSChristopher Di Bella static_assert(std::swappable_with<union_swap::adl_swappable&, int&>);
60724dd2d2fSChristopher Di Bella } // namespace adl
60824dd2d2fSChristopher Di Bella 
60924dd2d2fSChristopher Di Bella namespace standard_types {
61024dd2d2fSChristopher Di Bella static_assert(
61124dd2d2fSChristopher Di Bella     check_swappable_with<std::array<int, 10>, std::array<int, 10> >());
61224dd2d2fSChristopher Di Bella static_assert(
61324dd2d2fSChristopher Di Bella     !check_swappable_with<std::array<int, 10>, std::array<double, 10> >());
61424dd2d2fSChristopher Di Bella static_assert(check_swappable_with<std::deque<int>, std::deque<int> >());
61524dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<std::deque<int>, std::vector<int> >());
61624dd2d2fSChristopher Di Bella static_assert(
61724dd2d2fSChristopher Di Bella     check_swappable_with<std::forward_list<int>, std::forward_list<int> >());
61824dd2d2fSChristopher Di Bella static_assert(
61924dd2d2fSChristopher Di Bella     !check_swappable_with<std::forward_list<int>, std::vector<int> >());
62024dd2d2fSChristopher Di Bella static_assert(check_swappable_with<std::list<int>, std::list<int> >());
62124dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<std::list<int>, std::vector<int> >());
62224dd2d2fSChristopher Di Bella 
62324dd2d2fSChristopher Di Bella static_assert(
62424dd2d2fSChristopher Di Bella     check_swappable_with<std::map<int, void*>, std::map<int, void*> >());
62524dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<std::map<int, void*>, std::vector<int> >());
62624dd2d2fSChristopher Di Bella static_assert(check_swappable_with<std::optional<std::vector<int> >,
62724dd2d2fSChristopher Di Bella                                    std::optional<std::vector<int> > >());
62824dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<std::optional<std::vector<int> >,
62924dd2d2fSChristopher Di Bella                                     std::vector<int> >());
63024dd2d2fSChristopher Di Bella static_assert(check_swappable_with<std::vector<int>, std::vector<int> >());
63124dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<std::vector<int>, int>());
63224dd2d2fSChristopher Di Bella } // namespace standard_types
63324dd2d2fSChristopher Di Bella 
63424dd2d2fSChristopher Di Bella namespace types_with_purpose {
63524dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<DeletedMoveCtor, DeletedMoveCtor>());
63624dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<ImplicitlyDeletedMoveCtor,
63724dd2d2fSChristopher Di Bella                                     ImplicitlyDeletedMoveCtor>());
63824dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<DeletedMoveAssign, DeletedMoveAssign>());
63924dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<ImplicitlyDeletedMoveAssign,
64024dd2d2fSChristopher Di Bella                                     ImplicitlyDeletedMoveAssign>());
64124dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<NonMovable, NonMovable>());
64224dd2d2fSChristopher Di Bella static_assert(
64324dd2d2fSChristopher Di Bella     !check_swappable_with<DerivedFromNonMovable, DerivedFromNonMovable>());
64424dd2d2fSChristopher Di Bella static_assert(!check_swappable_with<HasANonMovable, HasANonMovable>());
64524dd2d2fSChristopher Di Bella } // namespace types_with_purpose
64624dd2d2fSChristopher Di Bella 
647cedd07dfSChristopher Di Bella namespace LWG3175 {
648cedd07dfSChristopher Di Bella // Example taken directly from [concept.swappable]
649cedd07dfSChristopher Di Bella template <class T, std::swappable_with<T> U>
value_swap(T && t,U && u)650cedd07dfSChristopher Di Bella constexpr void value_swap(T&& t, U&& u) {
651cedd07dfSChristopher Di Bella   std::ranges::swap(std::forward<T>(t), std::forward<U>(u));
652cedd07dfSChristopher Di Bella }
653cedd07dfSChristopher Di Bella 
654cedd07dfSChristopher Di Bella template <std::swappable T>
lv_swap(T & t1,T & t2)655cedd07dfSChristopher Di Bella constexpr void lv_swap(T& t1, T& t2) {
656cedd07dfSChristopher Di Bella   std::ranges::swap(t1, t2);
657cedd07dfSChristopher Di Bella }
658cedd07dfSChristopher Di Bella 
659cedd07dfSChristopher Di Bella namespace N {
660cedd07dfSChristopher Di Bella struct A {
661cedd07dfSChristopher Di Bella   int m;
662cedd07dfSChristopher Di Bella };
663cedd07dfSChristopher Di Bella struct Proxy {
664cedd07dfSChristopher Di Bella   A* a;
ProxyLWG3175::N::Proxy665cedd07dfSChristopher Di Bella   constexpr Proxy(A& a_) : a{&a_} {}
swap(Proxy x,Proxy y)666cedd07dfSChristopher Di Bella   friend constexpr void swap(Proxy x, Proxy y) {
667cedd07dfSChristopher Di Bella     std::ranges::swap(*x.a, *y.a);
668cedd07dfSChristopher Di Bella   }
669cedd07dfSChristopher Di Bella };
proxy(A & a)670cedd07dfSChristopher Di Bella constexpr Proxy proxy(A& a) { return Proxy{a}; }
671cedd07dfSChristopher Di Bella } // namespace N
672cedd07dfSChristopher Di Bella 
CheckRegression()673*88b73a98SLouis Dionne constexpr bool CheckRegression() {
674cedd07dfSChristopher Di Bella   int i = 1, j = 2;
675cedd07dfSChristopher Di Bella   lv_swap(i, j);
676cedd07dfSChristopher Di Bella   assert(i == 2 && j == 1);
677cedd07dfSChristopher Di Bella 
678cedd07dfSChristopher Di Bella   N::A a1 = {5}, a2 = {-5};
679cedd07dfSChristopher Di Bella   value_swap(a1, proxy(a2));
680cedd07dfSChristopher Di Bella   assert(a1.m == -5 && a2.m == 5);
681cedd07dfSChristopher Di Bella   return true;
682cedd07dfSChristopher Di Bella }
683cedd07dfSChristopher Di Bella 
684cedd07dfSChristopher Di Bella static_assert(CheckRegression());
685cedd07dfSChristopher Di Bella } // namespace LWG3175
686