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