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