686 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// template<class T, class U>12// concept swappable_with = // see below13 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 false237static_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 fundamental245 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 void436 swap(s1 const&&,437 swappable_with_rvalue_ref_to_const_s1_but_not_swappable const&&);438 friend void439 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 void461 swap(s1 volatile&&,462 swappable_with_rvalue_ref_to_volatile_s1_but_not_swappable volatile&&);463 friend void464 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 void488 swap(s1 const volatile&&,489 swappable_with_rvalue_ref_to_cv_s1_but_not_swappable const volatile&&);490 friend void491 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_swap600static_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 adl608 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_types633 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_purpose646 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 N672 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 = {5}, a2 = {-5};679 value_swap(a1, proxy(a2));680 assert(a1.m == -5 && a2.m == 5);681 return true;682}683 684static_assert(CheckRegression());685} // namespace LWG3175686