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 T, class U>
12// concept swappable_with = // see below
13
14#include <concepts>
15
16#include <array>
17#include <cassert>
18#include <deque>
19#include <forward_list>
20#include <list>
21#include <map>
22#include <memory>
23#include <optional>
24#include <set>
25#include <unordered_map>
26#include <unordered_set>
27#include <vector>
28
29#include "type_classification/moveconstructible.h"
30#include "type_classification/swappable.h"
31
32template <class T, class U>
33constexpr bool check_swappable_with_impl() {
34 static_assert(std::swappable_with<T, U> == std::swappable_with<U, T>);
35 return std::swappable_with<T, U>;
36}
37
38template <class T, class U>
39constexpr bool check_swappable_with() {
40 static_assert(!check_swappable_with_impl<T, U>());
41 static_assert(!check_swappable_with_impl<T, U const>());
42 static_assert(!check_swappable_with_impl<T const, U>());
43 static_assert(!check_swappable_with_impl<T const, U const>());
44
45 static_assert(!check_swappable_with_impl<T, U&>());
46 static_assert(!check_swappable_with_impl<T, U const&>());
47 static_assert(!check_swappable_with_impl<T, U volatile&>());
48 static_assert(!check_swappable_with_impl<T, U const volatile&>());
49 static_assert(!check_swappable_with_impl<T const, U&>());
50 static_assert(!check_swappable_with_impl<T const, U const&>());
51 static_assert(!check_swappable_with_impl<T const, U volatile&>());
52 static_assert(!check_swappable_with_impl<T const, U const volatile&>());
53
54 static_assert(!check_swappable_with_impl<T&, U>());
55 static_assert(!check_swappable_with_impl<T&, U const>());
56 static_assert(!check_swappable_with_impl<T const&, U>());
57 static_assert(!check_swappable_with_impl<T const&, U const>());
58 static_assert(!check_swappable_with_impl<T volatile&, U>());
59 static_assert(!check_swappable_with_impl<T volatile&, U const>());
60 static_assert(!check_swappable_with_impl<T const volatile&, U>());
61 static_assert(!check_swappable_with_impl<T const volatile&, U const>());
62
63 static_assert(!check_swappable_with_impl<T&, U const&>());
64 static_assert(!check_swappable_with_impl<T&, U volatile&>());
65 static_assert(!check_swappable_with_impl<T&, U const volatile&>());
66 static_assert(!check_swappable_with_impl<T const&, U&>());
67 static_assert(!check_swappable_with_impl<T const&, U const&>());
68 static_assert(!check_swappable_with_impl<T const&, U volatile&>());
69 static_assert(!check_swappable_with_impl<T const&, U const volatile&>());
70 static_assert(!check_swappable_with_impl<T volatile&, U&>());
71 static_assert(!check_swappable_with_impl<T volatile&, U const&>());
72 static_assert(!check_swappable_with_impl<T volatile&, U const volatile&>());
73 static_assert(!check_swappable_with_impl<T const volatile&, U&>());
74 static_assert(!check_swappable_with_impl<T const volatile&, U const&>());
75 static_assert(!check_swappable_with_impl<T const volatile&, U volatile&>());
76 static_assert(
77 !check_swappable_with_impl<T const volatile&, U const volatile&>());
78
79 static_assert(!check_swappable_with_impl<T, U&&>());
80 static_assert(!check_swappable_with_impl<T, U const&&>());
81 static_assert(!check_swappable_with_impl<T, U volatile&&>());
82 static_assert(!check_swappable_with_impl<T, U const volatile&&>());
83 static_assert(!check_swappable_with_impl<T const, U&&>());
84 static_assert(!check_swappable_with_impl<T const, U const&&>());
85 static_assert(!check_swappable_with_impl<T const, U volatile&&>());
86 static_assert(!check_swappable_with_impl<T const, U const volatile&&>());
87
88 static_assert(!check_swappable_with_impl<T&&, U>());
89 static_assert(!check_swappable_with_impl<T&&, U const>());
90 static_assert(!check_swappable_with_impl<T const&&, U>());
91 static_assert(!check_swappable_with_impl<T const&&, U const>());
92 static_assert(!check_swappable_with_impl<T volatile&&, U>());
93 static_assert(!check_swappable_with_impl<T volatile&&, U const>());
94 static_assert(!check_swappable_with_impl<T const volatile&&, U>());
95 static_assert(!check_swappable_with_impl<T const volatile&&, U const>());
96
97 static_assert(!check_swappable_with_impl<T&, U&&>());
98 static_assert(!check_swappable_with_impl<T&, U const&&>());
99 static_assert(!check_swappable_with_impl<T&, U volatile&&>());
100 static_assert(!check_swappable_with_impl<T&, U const volatile&&>());
101 static_assert(!check_swappable_with_impl<T const&, U&&>());
102 static_assert(!check_swappable_with_impl<T const&, U const&&>());
103 static_assert(!check_swappable_with_impl<T const&, U volatile&&>());
104 static_assert(!check_swappable_with_impl<T const&, U const volatile&&>());
105 static_assert(!check_swappable_with_impl<T volatile&, U&&>());
106 static_assert(!check_swappable_with_impl<T volatile&, U const&&>());
107 static_assert(!check_swappable_with_impl<T volatile&, U volatile&&>());
108 static_assert(!check_swappable_with_impl<T volatile&, U const volatile&&>());
109 static_assert(!check_swappable_with_impl<T const volatile&, U&&>());
110 static_assert(!check_swappable_with_impl<T const volatile&, U const&&>());
111 static_assert(!check_swappable_with_impl<T const volatile&, U volatile&&>());
112 static_assert(
113 !check_swappable_with_impl<T const volatile&, U const volatile&&>());
114
115 static_assert(!check_swappable_with_impl<T&&, U&>());
116 static_assert(!check_swappable_with_impl<T&&, U const&>());
117 static_assert(!check_swappable_with_impl<T&&, U volatile&>());
118 static_assert(!check_swappable_with_impl<T&&, U const volatile&>());
119 static_assert(!check_swappable_with_impl<T const&&, U&>());
120 static_assert(!check_swappable_with_impl<T const&&, U const&>());
121 static_assert(!check_swappable_with_impl<T const&&, U volatile&>());
122 static_assert(!check_swappable_with_impl<T const&&, U const volatile&>());
123 static_assert(!check_swappable_with_impl<T volatile&&, U&>());
124 static_assert(!check_swappable_with_impl<T volatile&&, U const&>());
125 static_assert(!check_swappable_with_impl<T volatile&&, U volatile&>());
126 static_assert(!check_swappable_with_impl<T volatile&&, U const volatile&>());
127 static_assert(!check_swappable_with_impl<T const volatile&&, U&>());
128 static_assert(!check_swappable_with_impl<T const volatile&&, U const&>());
129 static_assert(!check_swappable_with_impl<T const volatile&&, U volatile&>());
130 static_assert(
131 !check_swappable_with_impl<T const volatile&&, U const volatile&>());
132
133 static_assert(!check_swappable_with_impl<T&&, U&&>());
134 static_assert(!check_swappable_with_impl<T&&, U const&&>());
135 static_assert(!check_swappable_with_impl<T&&, U volatile&&>());
136 static_assert(!check_swappable_with_impl<T&&, U const volatile&&>());
137 static_assert(!check_swappable_with_impl<T const&&, U&&>());
138 static_assert(!check_swappable_with_impl<T const&&, U const&&>());
139 static_assert(!check_swappable_with_impl<T const&&, U volatile&&>());
140 static_assert(!check_swappable_with_impl<T const&&, U const volatile&&>());
141 static_assert(!check_swappable_with_impl<T volatile&&, U&&>());
142 static_assert(!check_swappable_with_impl<T volatile&&, U const&&>());
143 static_assert(!check_swappable_with_impl<T volatile&&, U volatile&&>());
144 static_assert(!check_swappable_with_impl<T volatile&&, U const volatile&&>());
145 static_assert(!check_swappable_with_impl<T const volatile&&, U&&>());
146 static_assert(!check_swappable_with_impl<T const volatile&&, U const&&>());
147 static_assert(!check_swappable_with_impl<T const volatile&&, U volatile&&>());
148 static_assert(
149 !check_swappable_with_impl<T const volatile&&, U const volatile&&>());
150 return check_swappable_with_impl<T&, U&>();
151}
152
153template <class T, class U>
154constexpr bool check_swappable_with_including_lvalue_ref_to_volatile() {
155 constexpr auto result = check_swappable_with<T, U>();
156 static_assert(check_swappable_with_impl<T volatile&, U volatile&>() ==
157 result);
158 return result;
159}
160
161namespace fundamental {
162static_assert(
163 check_swappable_with_including_lvalue_ref_to_volatile<int, int>());
164static_assert(
165 check_swappable_with_including_lvalue_ref_to_volatile<double, double>());
166static_assert(
167 !check_swappable_with_including_lvalue_ref_to_volatile<int, double>());
168
169static_assert(
170 check_swappable_with_including_lvalue_ref_to_volatile<int*, int*>());
171static_assert(
172 !check_swappable_with_including_lvalue_ref_to_volatile<int, int*>());
173static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
174 int (*)(), int (*)()>());
175static_assert(
176 !check_swappable_with_including_lvalue_ref_to_volatile<int, int (*)()>());
177
178struct S {};
179static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<int, S>());
180static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
181 int S::*, int S::*>());
182static_assert(
183 !check_swappable_with_including_lvalue_ref_to_volatile<int, int S::*>());
184static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
185 int (S::*)(), int (S::*)()>());
186static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
187 int, int (S::*)()>());
188static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
189 int (S::*)() noexcept, int (S::*)() noexcept>());
190static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
191 int (S::*)() noexcept, int (S::*)()>());
192static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
193 int (S::*)() const, int (S::*)() const>());
194static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
195 int (S::*)() const, int (S::*)()>());
196static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
197 int (S::*)() const noexcept, int (S::*)() const noexcept>());
198static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
199 int (S::*)() const, int (S::*)() const noexcept>());
200static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
201 int (S::*)() volatile, int (S::*)() volatile>());
202static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
203 int (S::*)() volatile, int (S::*)()>());
204static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
205 int (S::*)() const volatile, int (S::*)() const volatile>());
206static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
207 int (S::*)() const volatile, int (S::*)()>());
208
209static_assert(
210 check_swappable_with_including_lvalue_ref_to_volatile<int[5], int[5]>());
211static_assert(
212 !check_swappable_with_including_lvalue_ref_to_volatile<int[5], int[6]>());
213static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
214 int[5], double[5]>());
215static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
216 int[5], double[6]>());
217static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<int[5][6],
218 int[5]>());
219static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<int[5][6],
220 int[6]>());
221static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
222 int[5][6], double[5]>());
223static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
224 int[5][6], double[6]>());
225static_assert(check_swappable_with_including_lvalue_ref_to_volatile<
226 int[5][6], int[5][6]>());
227static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
228 int[5][6], int[5][4]>());
229static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
230 int[5][6], int[6][5]>());
231static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
232 int[5][6], double[5][6]>());
233static_assert(!check_swappable_with_including_lvalue_ref_to_volatile<
234 int[5][6], double[6][5]>());
235
236// always false
237static_assert(!check_swappable_with_impl<void, void>());
238static_assert(!check_swappable_with_impl<int, void>());
239static_assert(!check_swappable_with_impl<int&, void>());
240static_assert(!check_swappable_with_impl<void, int>());
241static_assert(!check_swappable_with_impl<void, int&>());
242static_assert(!check_swappable_with_impl<int, int()>());
243static_assert(!check_swappable_with_impl<int, int (&)()>());
244} // namespace fundamental
245
246namespace adl {
247static_assert(
248 check_swappable_with<lvalue_adl_swappable, lvalue_adl_swappable>());
249static_assert(check_swappable_with<lvalue_rvalue_adl_swappable,
250 lvalue_rvalue_adl_swappable>());
251static_assert(check_swappable_with<rvalue_lvalue_adl_swappable,
252 rvalue_lvalue_adl_swappable>());
253static_assert(
254 check_swappable_with_impl<rvalue_adl_swappable, rvalue_adl_swappable>());
255static_assert(!check_swappable_with_impl<lvalue_rvalue_adl_swappable&,
256 lvalue_rvalue_adl_swappable&&>());
257
258struct s1 {};
259struct no_common_reference_with_s1 {
260 friend void swap(s1&, no_common_reference_with_s1&);
261 friend void swap(no_common_reference_with_s1&, s1&);
262};
263static_assert(!check_swappable_with<s1, no_common_reference_with_s1>());
264
265struct one_way_swappable_with_s1 {
266 friend void swap(s1&, one_way_swappable_with_s1&);
267 operator s1();
268};
269static_assert(std::common_reference_with<one_way_swappable_with_s1, s1>);
270static_assert(!check_swappable_with<one_way_swappable_with_s1, s1>());
271
272struct one_way_swappable_with_s1_other_way {
273 friend void swap(one_way_swappable_with_s1_other_way&, s1&);
274 operator s1();
275};
276static_assert(
277 std::common_reference_with<one_way_swappable_with_s1_other_way, s1>);
278static_assert(!check_swappable_with<one_way_swappable_with_s1_other_way, s1>());
279
280struct can_swap_with_s1_but_not_swappable {
281 can_swap_with_s1_but_not_swappable(can_swap_with_s1_but_not_swappable&&) =
282 delete;
283 friend void swap(s1&, can_swap_with_s1_but_not_swappable&);
284 friend void swap(can_swap_with_s1_but_not_swappable&, s1&);
285
286 operator s1() const;
287};
288static_assert(
289 std::common_reference_with<can_swap_with_s1_but_not_swappable, s1>);
290static_assert(!std::swappable<can_swap_with_s1_but_not_swappable>);
291static_assert(
292 !check_swappable_with<can_swap_with_s1_but_not_swappable&, s1&>());
293
294struct swappable_with_s1 {
295 friend void swap(s1&, swappable_with_s1&);
296 friend void swap(swappable_with_s1&, s1&);
297 operator s1() const;
298};
299static_assert(check_swappable_with<swappable_with_s1, s1>());
300
301struct swappable_with_const_s1_but_not_swappable {
302 swappable_with_const_s1_but_not_swappable(
303 swappable_with_const_s1_but_not_swappable const&);
304 swappable_with_const_s1_but_not_swappable(
305 swappable_with_const_s1_but_not_swappable const&&);
306 swappable_with_const_s1_but_not_swappable&
307 operator=(swappable_with_const_s1_but_not_swappable const&);
308 swappable_with_const_s1_but_not_swappable&
309 operator=(swappable_with_const_s1_but_not_swappable const&&);
310
311 friend void swap(s1 const&, swappable_with_const_s1_but_not_swappable const&);
312 friend void swap(swappable_with_const_s1_but_not_swappable const&, s1 const&);
313
314 operator s1 const &() const;
315};
316static_assert(
317 !std::swappable<swappable_with_const_s1_but_not_swappable const&>);
318static_assert(!std::swappable_with<
319 swappable_with_const_s1_but_not_swappable const&, s1 const&>);
320
321struct swappable_with_volatile_s1_but_not_swappable {
322 swappable_with_volatile_s1_but_not_swappable(
323 swappable_with_volatile_s1_but_not_swappable volatile&);
324 swappable_with_volatile_s1_but_not_swappable(
325 swappable_with_volatile_s1_but_not_swappable volatile&&);
326 swappable_with_volatile_s1_but_not_swappable&
327 operator=(swappable_with_volatile_s1_but_not_swappable volatile&);
328 swappable_with_volatile_s1_but_not_swappable&
329 operator=(swappable_with_volatile_s1_but_not_swappable volatile&&);
330
331 friend void swap(s1 volatile&,
332 swappable_with_volatile_s1_but_not_swappable volatile&);
333 friend void swap(swappable_with_volatile_s1_but_not_swappable volatile&,
334 s1 volatile&);
335
336 operator s1 volatile &() volatile;
337};
338static_assert(
339 !std::swappable<swappable_with_volatile_s1_but_not_swappable volatile&>);
340static_assert(
341 !std::swappable_with<swappable_with_volatile_s1_but_not_swappable volatile&,
342 s1 volatile&>);
343
344struct swappable_with_cv_s1_but_not_swappable {
345 swappable_with_cv_s1_but_not_swappable(
346 swappable_with_cv_s1_but_not_swappable const volatile&);
347 swappable_with_cv_s1_but_not_swappable(
348 swappable_with_cv_s1_but_not_swappable const volatile&&);
349 swappable_with_cv_s1_but_not_swappable&
350 operator=(swappable_with_cv_s1_but_not_swappable const volatile&);
351 swappable_with_cv_s1_but_not_swappable&
352 operator=(swappable_with_cv_s1_but_not_swappable const volatile&&);
353
354 friend void swap(s1 const volatile&,
355 swappable_with_cv_s1_but_not_swappable const volatile&);
356 friend void swap(swappable_with_cv_s1_but_not_swappable const volatile&,
357 s1 const volatile&);
358
359 operator s1 const volatile &() const volatile;
360};
361static_assert(
362 !std::swappable<swappable_with_cv_s1_but_not_swappable const volatile&>);
363static_assert(
364 !std::swappable_with<swappable_with_cv_s1_but_not_swappable const volatile&,
365 s1 const volatile&>);
366
367struct s2 {
368 friend void swap(s2 const&, s2 const&);
369 friend void swap(s2 volatile&, s2 volatile&);
370 friend void swap(s2 const volatile&, s2 const volatile&);
371};
372
373struct swappable_with_const_s2 {
374 swappable_with_const_s2(swappable_with_const_s2 const&);
375 swappable_with_const_s2(swappable_with_const_s2 const&&);
376 swappable_with_const_s2& operator=(swappable_with_const_s2 const&);
377 swappable_with_const_s2& operator=(swappable_with_const_s2 const&&);
378
379 friend void swap(swappable_with_const_s2 const&,
380 swappable_with_const_s2 const&);
381 friend void swap(s2 const&, swappable_with_const_s2 const&);
382 friend void swap(swappable_with_const_s2 const&, s2 const&);
383
384 operator s2 const &() const;
385};
386static_assert(std::swappable_with<swappable_with_const_s2 const&, s2 const&>);
387
388struct swappable_with_volatile_s2 {
389 swappable_with_volatile_s2(swappable_with_volatile_s2 volatile&);
390 swappable_with_volatile_s2(swappable_with_volatile_s2 volatile&&);
391 swappable_with_volatile_s2& operator=(swappable_with_volatile_s2 volatile&);
392 swappable_with_volatile_s2& operator=(swappable_with_volatile_s2 volatile&&);
393
394 friend void swap(swappable_with_volatile_s2 volatile&,
395 swappable_with_volatile_s2 volatile&);
396 friend void swap(s2 volatile&, swappable_with_volatile_s2 volatile&);
397 friend void swap(swappable_with_volatile_s2 volatile&, s2 volatile&);
398
399 operator s2 volatile &() volatile;
400};
401static_assert(
402 std::swappable_with<swappable_with_volatile_s2 volatile&, s2 volatile&>);
403
404struct swappable_with_cv_s2 {
405 swappable_with_cv_s2(swappable_with_cv_s2 const volatile&);
406 swappable_with_cv_s2(swappable_with_cv_s2 const volatile&&);
407 swappable_with_cv_s2& operator=(swappable_with_cv_s2 const volatile&);
408 swappable_with_cv_s2& operator=(swappable_with_cv_s2 const volatile&&);
409
410 friend void swap(swappable_with_cv_s2 const volatile&,
411 swappable_with_cv_s2 const volatile&);
412 friend void swap(s2 const volatile&, swappable_with_cv_s2 const volatile&);
413 friend void swap(swappable_with_cv_s2 const volatile&, s2 const volatile&);
414
415 operator s2 const volatile &() const volatile;
416};
417static_assert(std::swappable_with<swappable_with_cv_s2 const volatile&,
418 s2 const volatile&>);
419
420struct swappable_with_rvalue_ref_to_s1_but_not_swappable {
421 friend void swap(swappable_with_rvalue_ref_to_s1_but_not_swappable&&,
422 swappable_with_rvalue_ref_to_s1_but_not_swappable&&);
423 friend void swap(s1&&, swappable_with_rvalue_ref_to_s1_but_not_swappable&&);
424 friend void swap(swappable_with_rvalue_ref_to_s1_but_not_swappable&&, s1&&);
425
426 operator s1() const;
427};
428static_assert(
429 !std::swappable<swappable_with_rvalue_ref_to_s1_but_not_swappable const&&>);
430static_assert(
431 !std::swappable_with<
432 swappable_with_rvalue_ref_to_s1_but_not_swappable const&&, s1 const&&>);
433
434struct swappable_with_rvalue_ref_to_const_s1_but_not_swappable {
435 friend void
436 swap(s1 const&&,
437 swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&);
438 friend void
439 swap(swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&,
440 s1 const&&);
441
442 operator s1 const() const;
443};
444static_assert(!std::swappable<
445 swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&>);
446static_assert(!std::swappable_with<
447 swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&,
448 s1 const&&>);
449
450struct swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable {
451 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable(
452 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&);
453 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable(
454 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&);
455 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable& operator=(
456 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&);
457 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable& operator=(
458 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&);
459
460 friend void
461 swap(s1 volatile&&,
462 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&);
463 friend void
464 swap(swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&,
465 s1 volatile&&);
466
467 operator s1 volatile &&() volatile&&;
468};
469static_assert(
470 !std::swappable<
471 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&>);
472static_assert(
473 !std::swappable_with<
474 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&,
475 s1 volatile&&>);
476
477struct swappable_with_rvalue_ref_to_cv_s1_but_not_swappable {
478 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable(
479 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&);
480 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable(
481 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&);
482 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable& operator=(
483 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&);
484 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable& operator=(
485 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&);
486
487 friend void
488 swap(s1 const volatile&&,
489 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&);
490 friend void
491 swap(swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&,
492 s1 const volatile&&);
493
494 operator s1 const volatile &&() const volatile&&;
495};
496static_assert(
497 !std::swappable<
498 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&>);
499static_assert(
500 !std::swappable_with<
501 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&,
502 s1 const volatile&&>);
503
504struct s3 {
505 friend void swap(s3&&, s3&&);
506 friend void swap(s3 const&&, s3 const&&);
507 friend void swap(s3 volatile&&, s3 volatile&&);
508 friend void swap(s3 const volatile&&, s3 const volatile&&);
509};
510
511struct swappable_with_rvalue_ref_to_s3 {
512 friend void swap(swappable_with_rvalue_ref_to_s3&&,
513 swappable_with_rvalue_ref_to_s3&&);
514 friend void swap(s3&&, swappable_with_rvalue_ref_to_s3&&);
515 friend void swap(swappable_with_rvalue_ref_to_s3&&, s3&&);
516
517 operator s3() const;
518};
519static_assert(std::swappable_with<swappable_with_rvalue_ref_to_s3&&, s3&&>);
520
521struct swappable_with_rvalue_ref_to_const_s3 {
522 swappable_with_rvalue_ref_to_const_s3(
523 swappable_with_rvalue_ref_to_const_s3 const&);
524 swappable_with_rvalue_ref_to_const_s3(
525 swappable_with_rvalue_ref_to_const_s3 const&&);
526 swappable_with_rvalue_ref_to_const_s3&
527 operator=(swappable_with_rvalue_ref_to_const_s3 const&);
528 swappable_with_rvalue_ref_to_const_s3&
529 operator=(swappable_with_rvalue_ref_to_const_s3 const&&);
530
531 friend void swap(swappable_with_rvalue_ref_to_const_s3 const&&,
532 swappable_with_rvalue_ref_to_const_s3 const&&);
533 friend void swap(s3 const&&, swappable_with_rvalue_ref_to_const_s3 const&&);
534 friend void swap(swappable_with_rvalue_ref_to_const_s3 const&&, s3 const&&);
535
536 operator s3() const;
537};
538static_assert(std::swappable_with<swappable_with_rvalue_ref_to_const_s3 const&&,
539 s3 const&&>);
540
541struct swappable_with_rvalue_ref_to_volatile_s3 {
542 swappable_with_rvalue_ref_to_volatile_s3(
543 swappable_with_rvalue_ref_to_volatile_s3 volatile&);
544 swappable_with_rvalue_ref_to_volatile_s3(
545 swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
546 swappable_with_rvalue_ref_to_volatile_s3&
547 operator=(swappable_with_rvalue_ref_to_volatile_s3 volatile&);
548 swappable_with_rvalue_ref_to_volatile_s3&
549 operator=(swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
550
551 friend void swap(swappable_with_rvalue_ref_to_volatile_s3 volatile&&,
552 swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
553 friend void swap(s3 volatile&&,
554 swappable_with_rvalue_ref_to_volatile_s3 volatile&&);
555 friend void swap(swappable_with_rvalue_ref_to_volatile_s3 volatile&&,
556 s3 volatile&&);
557
558 operator s3 volatile &&() volatile;
559};
560static_assert(
561 std::swappable_with<swappable_with_rvalue_ref_to_volatile_s3 volatile&&,
562 s3 volatile&&>);
563
564struct swappable_with_rvalue_ref_to_cv_s3 {
565 swappable_with_rvalue_ref_to_cv_s3(
566 swappable_with_rvalue_ref_to_cv_s3 const volatile&);
567 swappable_with_rvalue_ref_to_cv_s3(
568 swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
569 swappable_with_rvalue_ref_to_cv_s3&
570 operator=(swappable_with_rvalue_ref_to_cv_s3 const volatile&);
571 swappable_with_rvalue_ref_to_cv_s3&
572 operator=(swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
573
574 friend void swap(swappable_with_rvalue_ref_to_cv_s3 const volatile&&,
575 swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
576 friend void swap(s3 const volatile&&,
577 swappable_with_rvalue_ref_to_cv_s3 const volatile&&);
578 friend void swap(swappable_with_rvalue_ref_to_cv_s3 const volatile&&,
579 s3 const volatile&&);
580
581 operator s3 const volatile &&() const volatile;
582};
583static_assert(
584 std::swappable_with<swappable_with_rvalue_ref_to_cv_s3 const volatile&&,
585 s3 const volatile&&>);
586
587namespace union_swap {
588union adl_swappable {
589 int x;
590 double y;
591
592 operator int() const;
593};
594
595void swap(adl_swappable&, adl_swappable&) noexcept;
596void swap(adl_swappable&&, adl_swappable&&) noexcept;
597void swap(adl_swappable&, int&) noexcept;
598void swap(int&, adl_swappable&) noexcept;
599} // namespace union_swap
600static_assert(
601 std::swappable_with<union_swap::adl_swappable, union_swap::adl_swappable>);
602static_assert(std::swappable_with<union_swap::adl_swappable&,
603 union_swap::adl_swappable&>);
604static_assert(std::swappable_with<union_swap::adl_swappable&&,
605 union_swap::adl_swappable&&>);
606static_assert(std::swappable_with<union_swap::adl_swappable&, int&>);
607} // namespace adl
608
609namespace standard_types {
610static_assert(
611 check_swappable_with<std::array<int, 10>, std::array<int, 10> >());
612static_assert(
613 !check_swappable_with<std::array<int, 10>, std::array<double, 10> >());
614static_assert(check_swappable_with<std::deque<int>, std::deque<int> >());
615static_assert(!check_swappable_with<std::deque<int>, std::vector<int> >());
616static_assert(
617 check_swappable_with<std::forward_list<int>, std::forward_list<int> >());
618static_assert(
619 !check_swappable_with<std::forward_list<int>, std::vector<int> >());
620static_assert(check_swappable_with<std::list<int>, std::list<int> >());
621static_assert(!check_swappable_with<std::list<int>, std::vector<int> >());
622
623static_assert(
624 check_swappable_with<std::map<int, void*>, std::map<int, void*> >());
625static_assert(!check_swappable_with<std::map<int, void*>, std::vector<int> >());
626static_assert(check_swappable_with<std::optional<std::vector<int> >,
627 std::optional<std::vector<int> > >());
628static_assert(!check_swappable_with<std::optional<std::vector<int> >,
629 std::vector<int> >());
630static_assert(check_swappable_with<std::vector<int>, std::vector<int> >());
631static_assert(!check_swappable_with<std::vector<int>, int>());
632} // namespace standard_types
633
634namespace types_with_purpose {
635static_assert(!check_swappable_with<DeletedMoveCtor, DeletedMoveCtor>());
636static_assert(!check_swappable_with<ImplicitlyDeletedMoveCtor,
637 ImplicitlyDeletedMoveCtor>());
638static_assert(!check_swappable_with<DeletedMoveAssign, DeletedMoveAssign>());
639static_assert(!check_swappable_with<ImplicitlyDeletedMoveAssign,
640 ImplicitlyDeletedMoveAssign>());
641static_assert(!check_swappable_with<NonMovable, NonMovable>());
642static_assert(
643 !check_swappable_with<DerivedFromNonMovable, DerivedFromNonMovable>());
644static_assert(!check_swappable_with<HasANonMovable, HasANonMovable>());
645} // namespace types_with_purpose
646
647namespace LWG3175 {
648// Example taken directly from [concept.swappable]
649template <class T, std::swappable_with<T> U>
650constexpr void value_swap(T&& t, U&& u) {
651 std::ranges::swap(std::forward<T>(t), std::forward<U>(u));
652}
653
654template <std::swappable T>
655constexpr void lv_swap(T& t1, T& t2) {
656 std::ranges::swap(t1, t2);
657}
658
659namespace N {
660struct A {
661 int m;
662};
663struct Proxy {
664 A* a;
665 constexpr Proxy(A& a_) : a{&a_} {}
666 friend constexpr void swap(Proxy x, Proxy y) {
667 std::ranges::swap(*x.a, *y.a);
668 }
669};
670constexpr Proxy proxy(A& a) { return Proxy{a}; }
671} // namespace N
672
673constexpr bool CheckRegression() {
674 int i = 1, j = 2;
675 lv_swap(i, j);
676 assert(i == 2 && j == 1);
677
678 N::A a1 = {.m: 5}, a2 = {.m: -5};
679 value_swap(a1, proxy(a&: a2));
680 assert(a1.m == -5 && a2.m == 5);
681 return true;
682}
683
684static_assert(CheckRegression());
685} // namespace LWG3175
686

source code of libcxx/test/std/concepts/concepts.lang/concept.swappable/swappable_with.compile.pass.cpp