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 From, class To> 13 // concept common_with; 14 15 #include <concepts> 16 #include <type_traits> 17 18 #include "test_macros.h" 19 20 template <class T, class U> 21 constexpr bool CheckCommonWith() noexcept { 22 constexpr bool result = std::common_with<T, U>; 23 static_assert(std::common_with<T, U&> == result); 24 static_assert(std::common_with<T, const U&> == result); 25 static_assert(std::common_with<T, volatile U&> == result); 26 static_assert(std::common_with<T, const volatile U&> == result); 27 static_assert(std::common_with<T, U&&> == result); 28 static_assert(std::common_with<T, const U&&> == result); 29 static_assert(std::common_with<T, volatile U&&> == result); 30 static_assert(std::common_with<T, const volatile U&&> == result); 31 static_assert(std::common_with<T&, U&&> == result); 32 static_assert(std::common_with<T&, const U&&> == result); 33 static_assert(std::common_with<T&, volatile U&&> == result); 34 static_assert(std::common_with<T&, const volatile U&&> == result); 35 static_assert(std::common_with<const T&, U&&> == result); 36 static_assert(std::common_with<const T&, const U&&> == result); 37 static_assert(std::common_with<const T&, volatile U&&> == result); 38 static_assert(std::common_with<const T&, const volatile U&&> == result); 39 static_assert(std::common_with<volatile T&, U&&> == result); 40 static_assert(std::common_with<volatile T&, const U&&> == result); 41 static_assert(std::common_with<volatile T&, volatile U&&> == result); 42 static_assert(std::common_with<volatile T&, const volatile U&&> == result); 43 static_assert(std::common_with<const volatile T&, U&&> == result); 44 static_assert(std::common_with<const volatile T&, const U&&> == result); 45 static_assert(std::common_with<const volatile T&, volatile U&&> == result); 46 static_assert(std::common_with<const volatile T&, const volatile U&&> == 47 result); 48 return result; 49 } 50 51 template <class T, class U> 52 constexpr bool HasValidCommonType() noexcept { 53 return requires { typename std::common_type_t<T, U>; } 54 &&std::same_as<std::common_type_t<T, U>, std::common_type_t<U, T> >; 55 } 56 57 namespace BuiltinTypes { 58 // fundamental types 59 static_assert(std::common_with<void, void>); 60 static_assert(CheckCommonWith<int, int>()); 61 static_assert(CheckCommonWith<int, long>()); 62 static_assert(CheckCommonWith<int, unsigned char>()); 63 #ifndef _LIBCPP_HAS_NO_INT128 64 static_assert(CheckCommonWith<int, __int128_t>()); 65 #endif 66 static_assert(CheckCommonWith<int, double>()); 67 68 // arrays 69 static_assert(CheckCommonWith<int[5], int[5]>()); 70 71 // pointers 72 static_assert(CheckCommonWith<int*, int*>()); 73 static_assert(CheckCommonWith<int*, const int*>()); 74 static_assert(CheckCommonWith<int*, volatile int*>()); 75 static_assert(CheckCommonWith<int*, const volatile int*>()); 76 static_assert(CheckCommonWith<const int*, const int*>()); 77 static_assert(CheckCommonWith<const int*, volatile int*>()); 78 static_assert(CheckCommonWith<const int*, const volatile int*>()); 79 static_assert(CheckCommonWith<volatile int*, const int*>()); 80 static_assert(CheckCommonWith<volatile int*, volatile int*>()); 81 static_assert(CheckCommonWith<volatile int*, const volatile int*>()); 82 static_assert(CheckCommonWith<const volatile int*, const int*>()); 83 static_assert(CheckCommonWith<const volatile int*, volatile int*>()); 84 static_assert(CheckCommonWith<const volatile int*, const volatile int*>()); 85 86 static_assert(CheckCommonWith<int (*)(), int (*)()>()); 87 static_assert(CheckCommonWith<int (*)(), int (*)() noexcept>()); 88 static_assert(CheckCommonWith<int (&)(), int (&)()>()); 89 static_assert(CheckCommonWith<int (&)(), int (&)() noexcept>()); 90 static_assert(CheckCommonWith<int (&)(), int (*)()>()); 91 static_assert(CheckCommonWith<int (&)(), int (*)() noexcept>()); 92 93 struct S {}; 94 static_assert(CheckCommonWith<int S::*, int S::*>()); 95 static_assert(CheckCommonWith<int S::*, const int S::*>()); 96 static_assert(CheckCommonWith<int (S::*)(), int (S::*)()>()); 97 static_assert(CheckCommonWith<int (S::*)(), int (S::*)() noexcept>()); 98 static_assert(CheckCommonWith<int (S::*)() const, int (S::*)() const>()); 99 static_assert( 100 CheckCommonWith<int (S::*)() const, int (S::*)() const noexcept>()); 101 static_assert(CheckCommonWith<int (S::*)() volatile, int (S::*)() volatile>()); 102 static_assert( 103 CheckCommonWith<int (S::*)() volatile, int (S::*)() volatile noexcept>()); 104 static_assert(CheckCommonWith<int (S::*)() const volatile, 105 int (S::*)() const volatile>()); 106 static_assert(CheckCommonWith<int (S::*)() const volatile, 107 int (S::*)() const volatile noexcept>()); 108 109 // nonsense 110 static_assert(!CheckCommonWith<double, float*>()); 111 static_assert(!CheckCommonWith<int, int[5]>()); 112 static_assert(!CheckCommonWith<int*, long*>()); 113 static_assert(!CheckCommonWith<int*, unsigned int*>()); 114 static_assert(!CheckCommonWith<int (*)(), int (*)(int)>()); 115 static_assert(!CheckCommonWith<int S::*, float S::*>()); 116 static_assert(!CheckCommonWith<int (S::*)(), int (S::*)() const>()); 117 static_assert(!CheckCommonWith<int (S::*)(), int (S::*)() volatile>()); 118 static_assert(!CheckCommonWith<int (S::*)(), int (S::*)() const volatile>()); 119 static_assert(!CheckCommonWith<int (S::*)() const, int (S::*)() volatile>()); 120 static_assert( 121 !CheckCommonWith<int (S::*)() const, int (S::*)() const volatile>()); 122 static_assert( 123 !CheckCommonWith<int (S::*)() volatile, int (S::*)() const volatile>()); 124 } // namespace BuiltinTypes 125 126 namespace NoDefaultCommonType { 127 class T {}; 128 129 static_assert(!CheckCommonWith<T, int>()); 130 static_assert(!CheckCommonWith<int, T>()); 131 static_assert(!CheckCommonWith<T, int[10]>()); 132 static_assert(!CheckCommonWith<T[10], int>()); 133 static_assert(!CheckCommonWith<T*, int*>()); 134 static_assert(!CheckCommonWith<T*, const int*>()); 135 static_assert(!CheckCommonWith<T*, volatile int*>()); 136 static_assert(!CheckCommonWith<T*, const volatile int*>()); 137 static_assert(!CheckCommonWith<const T*, int*>()); 138 static_assert(!CheckCommonWith<volatile T*, int*>()); 139 static_assert(!CheckCommonWith<const volatile T*, int*>()); 140 static_assert(!CheckCommonWith<const T*, const int*>()); 141 static_assert(!CheckCommonWith<const T*, volatile int*>()); 142 static_assert(!CheckCommonWith<const T*, const volatile int*>()); 143 static_assert(!CheckCommonWith<const T*, const int*>()); 144 static_assert(!CheckCommonWith<volatile T*, const int*>()); 145 static_assert(!CheckCommonWith<const volatile T*, const int*>()); 146 static_assert(!CheckCommonWith<volatile T*, const int*>()); 147 static_assert(!CheckCommonWith<volatile T*, volatile int*>()); 148 static_assert(!CheckCommonWith<volatile T*, const volatile int*>()); 149 static_assert(!CheckCommonWith<const T*, volatile int*>()); 150 static_assert(!CheckCommonWith<volatile T*, volatile int*>()); 151 static_assert(!CheckCommonWith<const volatile T*, volatile int*>()); 152 static_assert(!CheckCommonWith<const volatile T*, const int*>()); 153 static_assert(!CheckCommonWith<const volatile T*, volatile int*>()); 154 static_assert(!CheckCommonWith<const volatile T*, const volatile int*>()); 155 static_assert(!CheckCommonWith<const T*, const volatile int*>()); 156 static_assert(!CheckCommonWith<volatile T*, const volatile int*>()); 157 static_assert(!CheckCommonWith<const volatile T*, const volatile int*>()); 158 static_assert(!CheckCommonWith<T&, int&>()); 159 static_assert(!CheckCommonWith<T&, const int&>()); 160 static_assert(!CheckCommonWith<T&, volatile int&>()); 161 static_assert(!CheckCommonWith<T&, const volatile int&>()); 162 static_assert(!CheckCommonWith<const T&, int&>()); 163 static_assert(!CheckCommonWith<volatile T&, int&>()); 164 static_assert(!CheckCommonWith<const volatile T&, int&>()); 165 static_assert(!CheckCommonWith<const T&, const int&>()); 166 static_assert(!CheckCommonWith<const T&, volatile int&>()); 167 static_assert(!CheckCommonWith<const T&, const volatile int&>()); 168 static_assert(!CheckCommonWith<const T&, const int&>()); 169 static_assert(!CheckCommonWith<volatile T&, const int&>()); 170 static_assert(!CheckCommonWith<const volatile T&, const int&>()); 171 static_assert(!CheckCommonWith<volatile T&, const int&>()); 172 static_assert(!CheckCommonWith<volatile T&, volatile int&>()); 173 static_assert(!CheckCommonWith<volatile T&, const volatile int&>()); 174 static_assert(!CheckCommonWith<const T&, volatile int&>()); 175 static_assert(!CheckCommonWith<volatile T&, volatile int&>()); 176 static_assert(!CheckCommonWith<const volatile T&, volatile int&>()); 177 static_assert(!CheckCommonWith<const volatile T&, const int&>()); 178 static_assert(!CheckCommonWith<const volatile T&, volatile int&>()); 179 static_assert(!CheckCommonWith<const volatile T&, const volatile int&>()); 180 static_assert(!CheckCommonWith<const T&, const volatile int&>()); 181 static_assert(!CheckCommonWith<volatile T&, const volatile int&>()); 182 static_assert(!CheckCommonWith<const volatile T&, const volatile int&>()); 183 static_assert(!CheckCommonWith<T&, int&&>()); 184 static_assert(!CheckCommonWith<T&, const int&&>()); 185 static_assert(!CheckCommonWith<T&, volatile int&&>()); 186 static_assert(!CheckCommonWith<T&, const volatile int&&>()); 187 static_assert(!CheckCommonWith<const T&, int&&>()); 188 static_assert(!CheckCommonWith<volatile T&, int&&>()); 189 static_assert(!CheckCommonWith<const volatile T&, int&&>()); 190 static_assert(!CheckCommonWith<const T&, const int&&>()); 191 static_assert(!CheckCommonWith<const T&, volatile int&&>()); 192 static_assert(!CheckCommonWith<const T&, const volatile int&&>()); 193 static_assert(!CheckCommonWith<const T&, const int&&>()); 194 static_assert(!CheckCommonWith<volatile T&, const int&&>()); 195 static_assert(!CheckCommonWith<const volatile T&, const int&&>()); 196 static_assert(!CheckCommonWith<volatile T&, const int&&>()); 197 static_assert(!CheckCommonWith<volatile T&, volatile int&&>()); 198 static_assert(!CheckCommonWith<volatile T&, const volatile int&&>()); 199 static_assert(!CheckCommonWith<const T&, volatile int&&>()); 200 static_assert(!CheckCommonWith<volatile T&, volatile int&&>()); 201 static_assert(!CheckCommonWith<const volatile T&, volatile int&&>()); 202 static_assert(!CheckCommonWith<const volatile T&, const int&&>()); 203 static_assert(!CheckCommonWith<const volatile T&, volatile int&&>()); 204 static_assert(!CheckCommonWith<const volatile T&, const volatile int&&>()); 205 static_assert(!CheckCommonWith<const T&, const volatile int&&>()); 206 static_assert(!CheckCommonWith<volatile T&, const volatile int&&>()); 207 static_assert(!CheckCommonWith<const volatile T&, const volatile int&&>()); 208 static_assert(!CheckCommonWith<T&&, int&>()); 209 static_assert(!CheckCommonWith<T&&, const int&>()); 210 static_assert(!CheckCommonWith<T&&, volatile int&>()); 211 static_assert(!CheckCommonWith<T&&, const volatile int&>()); 212 static_assert(!CheckCommonWith<const T&&, int&>()); 213 static_assert(!CheckCommonWith<volatile T&&, int&>()); 214 static_assert(!CheckCommonWith<const volatile T&&, int&>()); 215 static_assert(!CheckCommonWith<const T&&, const int&>()); 216 static_assert(!CheckCommonWith<const T&&, volatile int&>()); 217 static_assert(!CheckCommonWith<const T&&, const volatile int&>()); 218 static_assert(!CheckCommonWith<const T&&, const int&>()); 219 static_assert(!CheckCommonWith<volatile T&&, const int&>()); 220 static_assert(!CheckCommonWith<const volatile T&&, const int&>()); 221 static_assert(!CheckCommonWith<volatile T&&, const int&>()); 222 static_assert(!CheckCommonWith<volatile T&&, volatile int&>()); 223 static_assert(!CheckCommonWith<volatile T&&, const volatile int&>()); 224 static_assert(!CheckCommonWith<const T&&, volatile int&>()); 225 static_assert(!CheckCommonWith<volatile T&&, volatile int&>()); 226 static_assert(!CheckCommonWith<const volatile T&&, volatile int&>()); 227 static_assert(!CheckCommonWith<const volatile T&&, const int&>()); 228 static_assert(!CheckCommonWith<const volatile T&&, volatile int&>()); 229 static_assert(!CheckCommonWith<const volatile T&&, const volatile int&>()); 230 static_assert(!CheckCommonWith<const T&&, const volatile int&>()); 231 static_assert(!CheckCommonWith<volatile T&&, const volatile int&>()); 232 static_assert(!CheckCommonWith<const volatile T&&, const volatile int&>()); 233 static_assert(!CheckCommonWith<T&&, int&&>()); 234 static_assert(!CheckCommonWith<T&&, const int&&>()); 235 static_assert(!CheckCommonWith<T&&, volatile int&&>()); 236 static_assert(!CheckCommonWith<T&&, const volatile int&&>()); 237 static_assert(!CheckCommonWith<const T&&, int&&>()); 238 static_assert(!CheckCommonWith<volatile T&&, int&&>()); 239 static_assert(!CheckCommonWith<const volatile T&&, int&&>()); 240 static_assert(!CheckCommonWith<const T&&, const int&&>()); 241 static_assert(!CheckCommonWith<const T&&, volatile int&&>()); 242 static_assert(!CheckCommonWith<const T&&, const volatile int&&>()); 243 static_assert(!CheckCommonWith<const T&&, const int&&>()); 244 static_assert(!CheckCommonWith<volatile T&&, const int&&>()); 245 static_assert(!CheckCommonWith<const volatile T&&, const int&&>()); 246 static_assert(!CheckCommonWith<volatile T&&, const int&&>()); 247 static_assert(!CheckCommonWith<volatile T&&, volatile int&&>()); 248 static_assert(!CheckCommonWith<volatile T&&, const volatile int&&>()); 249 static_assert(!CheckCommonWith<const T&&, volatile int&&>()); 250 static_assert(!CheckCommonWith<volatile T&&, volatile int&&>()); 251 static_assert(!CheckCommonWith<const volatile T&&, volatile int&&>()); 252 static_assert(!CheckCommonWith<const volatile T&&, const int&&>()); 253 static_assert(!CheckCommonWith<const volatile T&&, volatile int&&>()); 254 static_assert(!CheckCommonWith<const volatile T&&, const volatile int&&>()); 255 static_assert(!CheckCommonWith<const T&&, const volatile int&&>()); 256 static_assert(!CheckCommonWith<volatile T&&, const volatile int&&>()); 257 static_assert(!CheckCommonWith<const volatile T&&, const volatile int&&>()); 258 } // namespace NoDefaultCommonType 259 260 struct BadBasicCommonType { 261 // This test is ill-formed, NDR. If it ever blows up in our faces: that's a good thing. 262 // In the meantime, the test should be included. If compiler support is added, then an include guard 263 // should be placed so the test doesn't get deleted. 264 }; 265 266 namespace std { 267 template <> 268 struct common_type<BadBasicCommonType, int> { 269 using type = BadBasicCommonType; 270 }; 271 272 template <> 273 struct common_type<int, BadBasicCommonType> { 274 using type = int; 275 }; 276 } // namespace std 277 static_assert(requires { 278 typename std::common_type_t<BadBasicCommonType, int>; 279 }); 280 static_assert(requires { 281 typename std::common_type_t<int, BadBasicCommonType>; 282 }); 283 static_assert(!std::same_as<std::common_type_t<BadBasicCommonType, int>, 284 std::common_type_t<int, BadBasicCommonType> >); 285 static_assert(!CheckCommonWith<BadBasicCommonType, int>()); 286 287 struct DullCommonType {}; 288 static_assert(!std::convertible_to<DullCommonType, int>); 289 290 struct T1 {}; 291 static_assert(!std::convertible_to<DullCommonType, T1>); 292 293 namespace std { 294 template <> 295 struct common_type<T1, int> { 296 using type = DullCommonType; 297 }; 298 299 template <> 300 struct common_type<int, T1> { 301 using type = DullCommonType; 302 }; 303 } // namespace std 304 static_assert(HasValidCommonType<T1, int>()); 305 static_assert(!CheckCommonWith<T1, int>()); 306 307 struct CommonTypeImplicitlyConstructibleFromInt { 308 explicit(false) CommonTypeImplicitlyConstructibleFromInt(int); 309 }; 310 static_assert(requires { 311 static_cast<CommonTypeImplicitlyConstructibleFromInt>(0); 312 }); 313 314 struct T2 {}; 315 static_assert( 316 !std::convertible_to<CommonTypeImplicitlyConstructibleFromInt, T2>); 317 318 namespace std { 319 template <> 320 struct common_type<T2, int> { 321 using type = CommonTypeImplicitlyConstructibleFromInt; 322 }; 323 324 template <> 325 struct common_type<int, T2> { 326 using type = CommonTypeImplicitlyConstructibleFromInt; 327 }; 328 } // namespace std 329 static_assert(HasValidCommonType<T2, int>()); 330 static_assert(!CheckCommonWith<T2, int>()); 331 332 struct CommonTypeExplicitlyConstructibleFromInt { 333 explicit CommonTypeExplicitlyConstructibleFromInt(int); 334 }; 335 static_assert(requires { 336 static_cast<CommonTypeExplicitlyConstructibleFromInt>(0); 337 }); 338 339 struct T3 {}; 340 static_assert( 341 !std::convertible_to<CommonTypeExplicitlyConstructibleFromInt, T2>); 342 343 namespace std { 344 template <> 345 struct common_type<T3, int> { 346 using type = CommonTypeExplicitlyConstructibleFromInt; 347 }; 348 349 template <> 350 struct common_type<int, T3> { 351 using type = CommonTypeExplicitlyConstructibleFromInt; 352 }; 353 } // namespace std 354 static_assert(HasValidCommonType<T3, int>()); 355 static_assert(!CheckCommonWith<T3, int>()); 356 357 struct T4 {}; 358 struct CommonTypeImplicitlyConstructibleFromT4 { 359 explicit(false) CommonTypeImplicitlyConstructibleFromT4(T4); 360 }; 361 static_assert(requires(T4 t4) { 362 static_cast<CommonTypeImplicitlyConstructibleFromT4>(t4); 363 }); 364 365 namespace std { 366 template <> 367 struct common_type<T4, int> { 368 using type = CommonTypeImplicitlyConstructibleFromT4; 369 }; 370 371 template <> 372 struct common_type<int, T4> { 373 using type = CommonTypeImplicitlyConstructibleFromT4; 374 }; 375 } // namespace std 376 static_assert(HasValidCommonType<T4, int>()); 377 static_assert(!CheckCommonWith<T4, int>()); 378 379 struct T5 {}; 380 struct CommonTypeExplicitlyConstructibleFromT5 { 381 explicit CommonTypeExplicitlyConstructibleFromT5(T5); 382 }; 383 static_assert(requires(T5 t5) { 384 static_cast<CommonTypeExplicitlyConstructibleFromT5>(t5); 385 }); 386 387 namespace std { 388 template <> 389 struct common_type<T5, int> { 390 using type = CommonTypeExplicitlyConstructibleFromT5; 391 }; 392 393 template <> 394 struct common_type<int, T5> { 395 using type = CommonTypeExplicitlyConstructibleFromT5; 396 }; 397 } // namespace std 398 static_assert(HasValidCommonType<T5, int>()); 399 static_assert(!CheckCommonWith<T5, int>()); 400 401 struct T6 {}; 402 struct CommonTypeNoCommonReference { 403 CommonTypeNoCommonReference(T6); 404 CommonTypeNoCommonReference(int); 405 }; 406 407 namespace std { 408 template <> 409 struct common_type<T6, int> { 410 using type = CommonTypeNoCommonReference; 411 }; 412 413 template <> 414 struct common_type<int, T6> { 415 using type = CommonTypeNoCommonReference; 416 }; 417 418 template <> 419 struct common_type<T6&, int&> {}; 420 421 template <> 422 struct common_type<int&, T6&> {}; 423 424 template <> 425 struct common_type<T6&, const int&> {}; 426 427 template <> 428 struct common_type<int&, const T6&> {}; 429 430 template <> 431 struct common_type<T6&, volatile int&> {}; 432 433 template <> 434 struct common_type<int&, volatile T6&> {}; 435 436 template <> 437 struct common_type<T6&, const volatile int&> {}; 438 439 template <> 440 struct common_type<int&, const volatile T6&> {}; 441 442 template <> 443 struct common_type<const T6&, int&> {}; 444 445 template <> 446 struct common_type<const int&, T6&> {}; 447 448 template <> 449 struct common_type<const T6&, const int&> {}; 450 451 template <> 452 struct common_type<const int&, const T6&> {}; 453 454 template <> 455 struct common_type<const T6&, volatile int&> {}; 456 457 template <> 458 struct common_type<const int&, volatile T6&> {}; 459 460 template <> 461 struct common_type<const T6&, const volatile int&> {}; 462 463 template <> 464 struct common_type<const int&, const volatile T6&> {}; 465 466 template <> 467 struct common_type<volatile T6&, int&> {}; 468 469 template <> 470 struct common_type<volatile int&, T6&> {}; 471 472 template <> 473 struct common_type<volatile T6&, const int&> {}; 474 475 template <> 476 struct common_type<volatile int&, const T6&> {}; 477 478 template <> 479 struct common_type<volatile T6&, volatile int&> {}; 480 481 template <> 482 struct common_type<volatile int&, volatile T6&> {}; 483 484 template <> 485 struct common_type<volatile T6&, const volatile int&> {}; 486 487 template <> 488 struct common_type<volatile int&, const volatile T6&> {}; 489 490 template <> 491 struct common_type<const volatile T6&, int&> {}; 492 493 template <> 494 struct common_type<const volatile int&, T6&> {}; 495 496 template <> 497 struct common_type<const volatile T6&, const int&> {}; 498 499 template <> 500 struct common_type<const volatile int&, const T6&> {}; 501 502 template <> 503 struct common_type<const volatile T6&, volatile int&> {}; 504 505 template <> 506 struct common_type<const volatile int&, volatile T6&> {}; 507 508 template <> 509 struct common_type<const volatile T6&, const volatile int&> {}; 510 511 template <> 512 struct common_type<const volatile int&, const volatile T6&> {}; 513 } // namespace std 514 515 template <typename T, typename U> 516 constexpr bool HasCommonReference() noexcept { 517 return requires { typename std::common_reference_t<T, U>; }; 518 } 519 520 static_assert(HasValidCommonType<T6, int>()); 521 static_assert(!HasCommonReference<const T6&, const int&>()); 522 static_assert(!CheckCommonWith<T6, int>()); 523 524 struct T7 {}; 525 struct CommonTypeNoMetaCommonReference { 526 CommonTypeNoMetaCommonReference(T7); 527 CommonTypeNoMetaCommonReference(int); 528 }; 529 530 namespace std { 531 template <> 532 struct common_type<T7, int> { 533 using type = CommonTypeNoMetaCommonReference; 534 }; 535 536 template <> 537 struct common_type<int, T7> { 538 using type = CommonTypeNoMetaCommonReference; 539 }; 540 541 template <> 542 struct common_type<T7&, int&> { 543 using type = void; 544 }; 545 546 template <> 547 struct common_type<int&, T7&> { 548 using type = void; 549 }; 550 551 template <> 552 struct common_type<T7&, const int&> { 553 using type = void; 554 }; 555 556 template <> 557 struct common_type<int&, const T7&> { 558 using type = void; 559 }; 560 561 template <> 562 struct common_type<T7&, volatile int&> { 563 using type = void; 564 }; 565 566 template <> 567 struct common_type<int&, volatile T7&> { 568 using type = void; 569 }; 570 571 template <> 572 struct common_type<T7&, const volatile int&> { 573 using type = void; 574 }; 575 576 template <> 577 struct common_type<int&, const volatile T7&> { 578 using type = void; 579 }; 580 581 template <> 582 struct common_type<const T7&, int&> { 583 using type = void; 584 }; 585 586 template <> 587 struct common_type<const int&, T7&> { 588 using type = void; 589 }; 590 591 template <> 592 struct common_type<const T7&, const int&> { 593 using type = void; 594 }; 595 596 template <> 597 struct common_type<const int&, const T7&> { 598 using type = void; 599 }; 600 601 template <> 602 struct common_type<const T7&, volatile int&> { 603 using type = void; 604 }; 605 606 template <> 607 struct common_type<const int&, volatile T7&> { 608 using type = void; 609 }; 610 611 template <> 612 struct common_type<const T7&, const volatile int&> { 613 using type = void; 614 }; 615 616 template <> 617 struct common_type<const int&, const volatile T7&> { 618 using type = void; 619 }; 620 621 template <> 622 struct common_type<volatile T7&, int&> { 623 using type = void; 624 }; 625 626 template <> 627 struct common_type<volatile int&, T7&> { 628 using type = void; 629 }; 630 631 template <> 632 struct common_type<volatile T7&, const int&> { 633 using type = void; 634 }; 635 636 template <> 637 struct common_type<volatile int&, const T7&> { 638 using type = void; 639 }; 640 641 template <> 642 struct common_type<volatile T7&, volatile int&> { 643 using type = void; 644 }; 645 646 template <> 647 struct common_type<volatile int&, volatile T7&> { 648 using type = void; 649 }; 650 651 template <> 652 struct common_type<volatile T7&, const volatile int&> { 653 using type = void; 654 }; 655 656 template <> 657 struct common_type<volatile int&, const volatile T7&> { 658 using type = void; 659 }; 660 661 template <> 662 struct common_type<const volatile T7&, int&> { 663 using type = void; 664 }; 665 666 template <> 667 struct common_type<const volatile int&, T7&> { 668 using type = void; 669 }; 670 671 template <> 672 struct common_type<const volatile T7&, const int&> { 673 using type = void; 674 }; 675 676 template <> 677 struct common_type<const volatile int&, const T7&> { 678 using type = void; 679 }; 680 681 template <> 682 struct common_type<const volatile T7&, volatile int&> { 683 using type = void; 684 }; 685 686 template <> 687 struct common_type<const volatile int&, volatile T7&> { 688 using type = void; 689 }; 690 691 template <> 692 struct common_type<const volatile T7&, const volatile int&> { 693 using type = void; 694 }; 695 696 template <> 697 struct common_type<const volatile int&, const volatile T7&> { 698 using type = void; 699 }; 700 } // namespace std 701 static_assert(HasValidCommonType<T7, int>()); 702 static_assert(HasValidCommonType<const T7&, const int&>()); 703 static_assert(HasCommonReference<const T7&, const int&>()); 704 static_assert( 705 !HasCommonReference<std::common_type_t<T7, int>&, 706 std::common_reference_t<const T7&, const int&> >()); 707 static_assert(!CheckCommonWith<T7, int>()); 708 709 struct CommonWithInt { 710 operator int() const volatile; 711 }; 712 713 namespace std { 714 template <> 715 struct common_type<CommonWithInt, int> { 716 using type = int; 717 }; 718 719 template <> 720 struct common_type<int, CommonWithInt> : common_type<CommonWithInt, int> {}; 721 722 template <> 723 struct common_type<CommonWithInt&, int&> : common_type<CommonWithInt, int> {}; 724 725 template <> 726 struct common_type<int&, CommonWithInt&> : common_type<CommonWithInt, int> {}; 727 728 template <> 729 struct common_type<CommonWithInt&, const int&> 730 : common_type<CommonWithInt, int> {}; 731 732 template <> 733 struct common_type<int&, const CommonWithInt&> 734 : common_type<CommonWithInt, int> {}; 735 736 template <> 737 struct common_type<CommonWithInt&, volatile int&> 738 : common_type<CommonWithInt, int> {}; 739 740 template <> 741 struct common_type<int&, volatile CommonWithInt&> 742 : common_type<CommonWithInt, int> {}; 743 744 template <> 745 struct common_type<CommonWithInt&, const volatile int&> 746 : common_type<CommonWithInt, int> {}; 747 748 template <> 749 struct common_type<int&, const volatile CommonWithInt&> 750 : common_type<CommonWithInt, int> {}; 751 752 template <> 753 struct common_type<const CommonWithInt&, int&> 754 : common_type<CommonWithInt, int> {}; 755 756 template <> 757 struct common_type<const int&, CommonWithInt&> 758 : common_type<CommonWithInt, int> {}; 759 760 template <> 761 struct common_type<const CommonWithInt&, const int&> 762 : common_type<CommonWithInt, int> {}; 763 764 template <> 765 struct common_type<const int&, const CommonWithInt&> 766 : common_type<CommonWithInt, int> {}; 767 768 template <> 769 struct common_type<const CommonWithInt&, volatile int&> 770 : common_type<CommonWithInt, int> {}; 771 772 template <> 773 struct common_type<const int&, volatile CommonWithInt&> 774 : common_type<CommonWithInt, int> {}; 775 776 template <> 777 struct common_type<const CommonWithInt&, const volatile int&> 778 : common_type<CommonWithInt, int> {}; 779 780 template <> 781 struct common_type<const int&, const volatile CommonWithInt&> 782 : common_type<CommonWithInt, int> {}; 783 784 template <> 785 struct common_type<volatile CommonWithInt&, int&> 786 : common_type<CommonWithInt, int> {}; 787 788 template <> 789 struct common_type<volatile int&, CommonWithInt&> 790 : common_type<CommonWithInt, int> {}; 791 792 template <> 793 struct common_type<volatile CommonWithInt&, const int&> 794 : common_type<CommonWithInt, int> {}; 795 796 template <> 797 struct common_type<volatile int&, const CommonWithInt&> 798 : common_type<CommonWithInt, int> {}; 799 800 template <> 801 struct common_type<volatile CommonWithInt&, volatile int&> 802 : common_type<CommonWithInt, int> {}; 803 804 template <> 805 struct common_type<volatile int&, volatile CommonWithInt&> 806 : common_type<CommonWithInt, int> {}; 807 808 template <> 809 struct common_type<volatile CommonWithInt&, const volatile int&> 810 : common_type<CommonWithInt, int> {}; 811 812 template <> 813 struct common_type<volatile int&, const volatile CommonWithInt&> 814 : common_type<CommonWithInt, int> {}; 815 816 template <> 817 struct common_type<const volatile CommonWithInt&, int&> 818 : common_type<CommonWithInt, int> {}; 819 820 template <> 821 struct common_type<const volatile int&, CommonWithInt&> 822 : common_type<CommonWithInt, int> {}; 823 824 template <> 825 struct common_type<const volatile CommonWithInt&, const int&> 826 : common_type<CommonWithInt, int> {}; 827 828 template <> 829 struct common_type<const volatile int&, const CommonWithInt&> 830 : common_type<CommonWithInt, int> {}; 831 832 template <> 833 struct common_type<const volatile CommonWithInt&, volatile int&> 834 : common_type<CommonWithInt, int> {}; 835 836 template <> 837 struct common_type<const volatile int&, volatile CommonWithInt&> 838 : common_type<CommonWithInt, int> {}; 839 840 template <> 841 struct common_type<const volatile CommonWithInt&, const volatile int&> 842 : common_type<CommonWithInt, int> {}; 843 844 template <> 845 struct common_type<const volatile int&, const volatile CommonWithInt&> 846 : common_type<CommonWithInt, int> {}; 847 } // namespace std 848 static_assert(CheckCommonWith<CommonWithInt, int>()); 849 850 struct CommonWithIntButRefLong { 851 operator int() const volatile; 852 }; 853 854 namespace std { 855 template <> 856 struct common_type<CommonWithIntButRefLong, int> { 857 using type = int; 858 }; 859 860 template <> 861 struct common_type<int, CommonWithIntButRefLong> 862 : common_type<CommonWithIntButRefLong, int> {}; 863 864 template <> 865 struct common_type<CommonWithIntButRefLong&, int&> { 866 using type = long; 867 }; 868 869 template <> 870 struct common_type<int&, CommonWithIntButRefLong&> 871 : common_type<CommonWithIntButRefLong&, int&> {}; 872 873 template <> 874 struct common_type<CommonWithIntButRefLong&, const int&> 875 : common_type<CommonWithIntButRefLong&, int&> {}; 876 877 template <> 878 struct common_type<int&, const CommonWithIntButRefLong&> 879 : common_type<CommonWithIntButRefLong&, int&> {}; 880 881 template <> 882 struct common_type<CommonWithIntButRefLong&, volatile int&> 883 : common_type<CommonWithIntButRefLong&, int&> {}; 884 885 template <> 886 struct common_type<int&, volatile CommonWithIntButRefLong&> 887 : common_type<CommonWithIntButRefLong&, int&> {}; 888 889 template <> 890 struct common_type<CommonWithIntButRefLong&, const volatile int&> 891 : common_type<CommonWithIntButRefLong&, int&> {}; 892 893 template <> 894 struct common_type<int&, const volatile CommonWithIntButRefLong&> 895 : common_type<CommonWithIntButRefLong&, int&> {}; 896 897 template <> 898 struct common_type<const CommonWithIntButRefLong&, int&> 899 : common_type<CommonWithIntButRefLong&, int&> {}; 900 901 template <> 902 struct common_type<const int&, CommonWithIntButRefLong&> 903 : common_type<CommonWithIntButRefLong&, int&> {}; 904 905 template <> 906 struct common_type<const CommonWithIntButRefLong&, const int&> 907 : common_type<CommonWithIntButRefLong&, int&> {}; 908 909 template <> 910 struct common_type<const int&, const CommonWithIntButRefLong&> 911 : common_type<CommonWithIntButRefLong&, int&> {}; 912 913 template <> 914 struct common_type<const CommonWithIntButRefLong&, volatile int&> 915 : common_type<CommonWithIntButRefLong&, int&> {}; 916 917 template <> 918 struct common_type<const int&, volatile CommonWithIntButRefLong&> 919 : common_type<CommonWithIntButRefLong&, int&> {}; 920 921 template <> 922 struct common_type<const CommonWithIntButRefLong&, const volatile int&> 923 : common_type<CommonWithIntButRefLong&, int&> {}; 924 925 template <> 926 struct common_type<const int&, const volatile CommonWithIntButRefLong&> 927 : common_type<CommonWithIntButRefLong&, int&> {}; 928 929 template <> 930 struct common_type<volatile CommonWithIntButRefLong&, int&> 931 : common_type<CommonWithIntButRefLong&, int&> {}; 932 933 template <> 934 struct common_type<volatile int&, CommonWithIntButRefLong&> 935 : common_type<CommonWithIntButRefLong&, int&> {}; 936 937 template <> 938 struct common_type<volatile CommonWithIntButRefLong&, const int&> 939 : common_type<CommonWithIntButRefLong&, int&> {}; 940 941 template <> 942 struct common_type<volatile int&, const CommonWithIntButRefLong&> 943 : common_type<CommonWithIntButRefLong&, int&> {}; 944 945 template <> 946 struct common_type<volatile CommonWithIntButRefLong&, volatile int&> 947 : common_type<CommonWithIntButRefLong&, int&> {}; 948 949 template <> 950 struct common_type<volatile int&, volatile CommonWithIntButRefLong&> 951 : common_type<CommonWithIntButRefLong&, int&> {}; 952 953 template <> 954 struct common_type<volatile CommonWithIntButRefLong&, const volatile int&> 955 : common_type<CommonWithIntButRefLong&, int&> {}; 956 957 template <> 958 struct common_type<volatile int&, const volatile CommonWithIntButRefLong&> 959 : common_type<CommonWithIntButRefLong&, int&> {}; 960 961 template <> 962 struct common_type<const volatile CommonWithIntButRefLong&, int&> 963 : common_type<CommonWithIntButRefLong&, int&> {}; 964 965 template <> 966 struct common_type<const volatile int&, CommonWithIntButRefLong&> 967 : common_type<CommonWithIntButRefLong&, int&> {}; 968 969 template <> 970 struct common_type<const volatile CommonWithIntButRefLong&, const int&> 971 : common_type<CommonWithIntButRefLong&, int&> {}; 972 973 template <> 974 struct common_type<const volatile int&, const CommonWithIntButRefLong&> 975 : common_type<CommonWithIntButRefLong&, int&> {}; 976 977 template <> 978 struct common_type<const volatile CommonWithIntButRefLong&, volatile int&> 979 : common_type<CommonWithIntButRefLong&, int&> {}; 980 981 template <> 982 struct common_type<const volatile int&, volatile CommonWithIntButRefLong&> 983 : common_type<CommonWithIntButRefLong&, int&> {}; 984 985 template <> 986 struct common_type<const volatile CommonWithIntButRefLong&, const volatile int&> 987 : common_type<CommonWithIntButRefLong&, int&> {}; 988 989 template <> 990 struct common_type<const volatile int&, const volatile CommonWithIntButRefLong&> 991 : common_type<CommonWithIntButRefLong&, int&> {}; 992 } // namespace std 993 static_assert(CheckCommonWith<CommonWithIntButRefLong, int>()); 994 995 int main(int, char**) { return 0; } 996