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