| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // UNSUPPORTED: c++03, c++11, c++14, c++17 |
| |
| // template<class From, class To> |
| // concept common_with; |
| |
| #include <concepts> |
| #include <type_traits> |
| |
| #include "test_macros.h" |
| |
| template <class T, class U> |
| constexpr bool CheckCommonWith() noexcept { |
| constexpr bool result = std::common_with<T, U>; |
| static_assert(std::common_with<T, U&> == result); |
| static_assert(std::common_with<T, const U&> == result); |
| static_assert(std::common_with<T, volatile U&> == result); |
| static_assert(std::common_with<T, const volatile U&> == result); |
| static_assert(std::common_with<T, U&&> == result); |
| static_assert(std::common_with<T, const U&&> == result); |
| static_assert(std::common_with<T, volatile U&&> == result); |
| static_assert(std::common_with<T, const volatile U&&> == result); |
| static_assert(std::common_with<T&, U&&> == result); |
| static_assert(std::common_with<T&, const U&&> == result); |
| static_assert(std::common_with<T&, volatile U&&> == result); |
| static_assert(std::common_with<T&, const volatile U&&> == result); |
| static_assert(std::common_with<const T&, U&&> == result); |
| static_assert(std::common_with<const T&, const U&&> == result); |
| static_assert(std::common_with<const T&, volatile U&&> == result); |
| static_assert(std::common_with<const T&, const volatile U&&> == result); |
| static_assert(std::common_with<volatile T&, U&&> == result); |
| static_assert(std::common_with<volatile T&, const U&&> == result); |
| static_assert(std::common_with<volatile T&, volatile U&&> == result); |
| static_assert(std::common_with<volatile T&, const volatile U&&> == result); |
| static_assert(std::common_with<const volatile T&, U&&> == result); |
| static_assert(std::common_with<const volatile T&, const U&&> == result); |
| static_assert(std::common_with<const volatile T&, volatile U&&> == result); |
| static_assert(std::common_with<const volatile T&, const volatile U&&> == |
| result); |
| return result; |
| } |
| |
| template <class T, class U> |
| constexpr bool HasValidCommonType() noexcept { |
| return requires { typename std::common_type_t<T, U>; } |
| &&std::same_as<std::common_type_t<T, U>, std::common_type_t<U, T> >; |
| } |
| |
| namespace BuiltinTypes { |
| // fundamental types |
| static_assert(std::common_with<void, void>); |
| static_assert(CheckCommonWith<int, int>()); |
| static_assert(CheckCommonWith<int, long>()); |
| static_assert(CheckCommonWith<int, unsigned char>()); |
| #ifndef TEST_HAS_NO_INT128 |
| static_assert(CheckCommonWith<int, __int128_t>()); |
| #endif |
| static_assert(CheckCommonWith<int, double>()); |
| |
| // arrays |
| static_assert(CheckCommonWith<int[5], int[5]>()); |
| |
| // pointers |
| static_assert(CheckCommonWith<int*, int*>()); |
| static_assert(CheckCommonWith<int*, const int*>()); |
| static_assert(CheckCommonWith<int*, volatile int*>()); |
| static_assert(CheckCommonWith<int*, const volatile int*>()); |
| static_assert(CheckCommonWith<const int*, const int*>()); |
| static_assert(CheckCommonWith<const int*, volatile int*>()); |
| static_assert(CheckCommonWith<const int*, const volatile int*>()); |
| static_assert(CheckCommonWith<volatile int*, const int*>()); |
| static_assert(CheckCommonWith<volatile int*, volatile int*>()); |
| static_assert(CheckCommonWith<volatile int*, const volatile int*>()); |
| static_assert(CheckCommonWith<const volatile int*, const int*>()); |
| static_assert(CheckCommonWith<const volatile int*, volatile int*>()); |
| static_assert(CheckCommonWith<const volatile int*, const volatile int*>()); |
| |
| static_assert(CheckCommonWith<int (*)(), int (*)()>()); |
| static_assert(CheckCommonWith<int (*)(), int (*)() noexcept>()); |
| static_assert(CheckCommonWith<int (&)(), int (&)()>()); |
| static_assert(CheckCommonWith<int (&)(), int (&)() noexcept>()); |
| static_assert(CheckCommonWith<int (&)(), int (*)()>()); |
| static_assert(CheckCommonWith<int (&)(), int (*)() noexcept>()); |
| |
| struct S {}; |
| static_assert(CheckCommonWith<int S::*, int S::*>()); |
| static_assert(CheckCommonWith<int S::*, const int S::*>()); |
| static_assert(CheckCommonWith<int (S::*)(), int (S::*)()>()); |
| static_assert(CheckCommonWith<int (S::*)(), int (S::*)() noexcept>()); |
| static_assert(CheckCommonWith<int (S::*)() const, int (S::*)() const>()); |
| static_assert( |
| CheckCommonWith<int (S::*)() const, int (S::*)() const noexcept>()); |
| static_assert(CheckCommonWith<int (S::*)() volatile, int (S::*)() volatile>()); |
| static_assert( |
| CheckCommonWith<int (S::*)() volatile, int (S::*)() volatile noexcept>()); |
| static_assert(CheckCommonWith<int (S::*)() const volatile, |
| int (S::*)() const volatile>()); |
| static_assert(CheckCommonWith<int (S::*)() const volatile, |
| int (S::*)() const volatile noexcept>()); |
| |
| // nonsense |
| static_assert(!CheckCommonWith<double, float*>()); |
| static_assert(!CheckCommonWith<int, int[5]>()); |
| static_assert(!CheckCommonWith<int*, long*>()); |
| static_assert(!CheckCommonWith<int*, unsigned int*>()); |
| static_assert(!CheckCommonWith<int (*)(), int (*)(int)>()); |
| static_assert(!CheckCommonWith<int S::*, float S::*>()); |
| static_assert(!CheckCommonWith<int (S::*)(), int (S::*)() const>()); |
| static_assert(!CheckCommonWith<int (S::*)(), int (S::*)() volatile>()); |
| static_assert(!CheckCommonWith<int (S::*)(), int (S::*)() const volatile>()); |
| static_assert(!CheckCommonWith<int (S::*)() const, int (S::*)() volatile>()); |
| static_assert( |
| !CheckCommonWith<int (S::*)() const, int (S::*)() const volatile>()); |
| static_assert( |
| !CheckCommonWith<int (S::*)() volatile, int (S::*)() const volatile>()); |
| } // namespace BuiltinTypes |
| |
| namespace NoDefaultCommonType { |
| class T {}; |
| |
| static_assert(!CheckCommonWith<T, int>()); |
| static_assert(!CheckCommonWith<int, T>()); |
| static_assert(!CheckCommonWith<T, int[10]>()); |
| static_assert(!CheckCommonWith<T[10], int>()); |
| static_assert(!CheckCommonWith<T*, int*>()); |
| static_assert(!CheckCommonWith<T*, const int*>()); |
| static_assert(!CheckCommonWith<T*, volatile int*>()); |
| static_assert(!CheckCommonWith<T*, const volatile int*>()); |
| static_assert(!CheckCommonWith<const T*, int*>()); |
| static_assert(!CheckCommonWith<volatile T*, int*>()); |
| static_assert(!CheckCommonWith<const volatile T*, int*>()); |
| static_assert(!CheckCommonWith<const T*, const int*>()); |
| static_assert(!CheckCommonWith<const T*, volatile int*>()); |
| static_assert(!CheckCommonWith<const T*, const volatile int*>()); |
| static_assert(!CheckCommonWith<const T*, const int*>()); |
| static_assert(!CheckCommonWith<volatile T*, const int*>()); |
| static_assert(!CheckCommonWith<const volatile T*, const int*>()); |
| static_assert(!CheckCommonWith<volatile T*, const int*>()); |
| static_assert(!CheckCommonWith<volatile T*, volatile int*>()); |
| static_assert(!CheckCommonWith<volatile T*, const volatile int*>()); |
| static_assert(!CheckCommonWith<const T*, volatile int*>()); |
| static_assert(!CheckCommonWith<volatile T*, volatile int*>()); |
| static_assert(!CheckCommonWith<const volatile T*, volatile int*>()); |
| static_assert(!CheckCommonWith<const volatile T*, const int*>()); |
| static_assert(!CheckCommonWith<const volatile T*, volatile int*>()); |
| static_assert(!CheckCommonWith<const volatile T*, const volatile int*>()); |
| static_assert(!CheckCommonWith<const T*, const volatile int*>()); |
| static_assert(!CheckCommonWith<volatile T*, const volatile int*>()); |
| static_assert(!CheckCommonWith<const volatile T*, const volatile int*>()); |
| static_assert(!CheckCommonWith<T&, int&>()); |
| static_assert(!CheckCommonWith<T&, const int&>()); |
| static_assert(!CheckCommonWith<T&, volatile int&>()); |
| static_assert(!CheckCommonWith<T&, const volatile int&>()); |
| static_assert(!CheckCommonWith<const T&, int&>()); |
| static_assert(!CheckCommonWith<volatile T&, int&>()); |
| static_assert(!CheckCommonWith<const volatile T&, int&>()); |
| static_assert(!CheckCommonWith<const T&, const int&>()); |
| static_assert(!CheckCommonWith<const T&, volatile int&>()); |
| static_assert(!CheckCommonWith<const T&, const volatile int&>()); |
| static_assert(!CheckCommonWith<const T&, const int&>()); |
| static_assert(!CheckCommonWith<volatile T&, const int&>()); |
| static_assert(!CheckCommonWith<const volatile T&, const int&>()); |
| static_assert(!CheckCommonWith<volatile T&, const int&>()); |
| static_assert(!CheckCommonWith<volatile T&, volatile int&>()); |
| static_assert(!CheckCommonWith<volatile T&, const volatile int&>()); |
| static_assert(!CheckCommonWith<const T&, volatile int&>()); |
| static_assert(!CheckCommonWith<volatile T&, volatile int&>()); |
| static_assert(!CheckCommonWith<const volatile T&, volatile int&>()); |
| static_assert(!CheckCommonWith<const volatile T&, const int&>()); |
| static_assert(!CheckCommonWith<const volatile T&, volatile int&>()); |
| static_assert(!CheckCommonWith<const volatile T&, const volatile int&>()); |
| static_assert(!CheckCommonWith<const T&, const volatile int&>()); |
| static_assert(!CheckCommonWith<volatile T&, const volatile int&>()); |
| static_assert(!CheckCommonWith<const volatile T&, const volatile int&>()); |
| static_assert(!CheckCommonWith<T&, int&&>()); |
| static_assert(!CheckCommonWith<T&, const int&&>()); |
| static_assert(!CheckCommonWith<T&, volatile int&&>()); |
| static_assert(!CheckCommonWith<T&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<const T&, int&&>()); |
| static_assert(!CheckCommonWith<volatile T&, int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&, int&&>()); |
| static_assert(!CheckCommonWith<const T&, const int&&>()); |
| static_assert(!CheckCommonWith<const T&, volatile int&&>()); |
| static_assert(!CheckCommonWith<const T&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<const T&, const int&&>()); |
| static_assert(!CheckCommonWith<volatile T&, const int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&, const int&&>()); |
| static_assert(!CheckCommonWith<volatile T&, const int&&>()); |
| static_assert(!CheckCommonWith<volatile T&, volatile int&&>()); |
| static_assert(!CheckCommonWith<volatile T&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<const T&, volatile int&&>()); |
| static_assert(!CheckCommonWith<volatile T&, volatile int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&, volatile int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&, const int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&, volatile int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<const T&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<volatile T&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<T&&, int&>()); |
| static_assert(!CheckCommonWith<T&&, const int&>()); |
| static_assert(!CheckCommonWith<T&&, volatile int&>()); |
| static_assert(!CheckCommonWith<T&&, const volatile int&>()); |
| static_assert(!CheckCommonWith<const T&&, int&>()); |
| static_assert(!CheckCommonWith<volatile T&&, int&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, int&>()); |
| static_assert(!CheckCommonWith<const T&&, const int&>()); |
| static_assert(!CheckCommonWith<const T&&, volatile int&>()); |
| static_assert(!CheckCommonWith<const T&&, const volatile int&>()); |
| static_assert(!CheckCommonWith<const T&&, const int&>()); |
| static_assert(!CheckCommonWith<volatile T&&, const int&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, const int&>()); |
| static_assert(!CheckCommonWith<volatile T&&, const int&>()); |
| static_assert(!CheckCommonWith<volatile T&&, volatile int&>()); |
| static_assert(!CheckCommonWith<volatile T&&, const volatile int&>()); |
| static_assert(!CheckCommonWith<const T&&, volatile int&>()); |
| static_assert(!CheckCommonWith<volatile T&&, volatile int&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, volatile int&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, const int&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, volatile int&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, const volatile int&>()); |
| static_assert(!CheckCommonWith<const T&&, const volatile int&>()); |
| static_assert(!CheckCommonWith<volatile T&&, const volatile int&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, const volatile int&>()); |
| static_assert(!CheckCommonWith<T&&, int&&>()); |
| static_assert(!CheckCommonWith<T&&, const int&&>()); |
| static_assert(!CheckCommonWith<T&&, volatile int&&>()); |
| static_assert(!CheckCommonWith<T&&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<const T&&, int&&>()); |
| static_assert(!CheckCommonWith<volatile T&&, int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, int&&>()); |
| static_assert(!CheckCommonWith<const T&&, const int&&>()); |
| static_assert(!CheckCommonWith<const T&&, volatile int&&>()); |
| static_assert(!CheckCommonWith<const T&&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<const T&&, const int&&>()); |
| static_assert(!CheckCommonWith<volatile T&&, const int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, const int&&>()); |
| static_assert(!CheckCommonWith<volatile T&&, const int&&>()); |
| static_assert(!CheckCommonWith<volatile T&&, volatile int&&>()); |
| static_assert(!CheckCommonWith<volatile T&&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<const T&&, volatile int&&>()); |
| static_assert(!CheckCommonWith<volatile T&&, volatile int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, volatile int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, const int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, volatile int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<const T&&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<volatile T&&, const volatile int&&>()); |
| static_assert(!CheckCommonWith<const volatile T&&, const volatile int&&>()); |
| } // namespace NoDefaultCommonType |
| |
| struct BadBasicCommonType { |
| // This test is ill-formed, NDR. If it ever blows up in our faces: that's a good thing. |
| // In the meantime, the test should be included. If compiler support is added, then an include guard |
| // should be placed so the test doesn't get deleted. |
| }; |
| |
| namespace std { |
| template <> |
| struct common_type<BadBasicCommonType, int> { |
| using type = BadBasicCommonType; |
| }; |
| |
| template <> |
| struct common_type<int, BadBasicCommonType> { |
| using type = int; |
| }; |
| } // namespace std |
| static_assert(requires { |
| typename std::common_type_t<BadBasicCommonType, int>; |
| }); |
| static_assert(requires { |
| typename std::common_type_t<int, BadBasicCommonType>; |
| }); |
| static_assert(!std::same_as<std::common_type_t<BadBasicCommonType, int>, |
| std::common_type_t<int, BadBasicCommonType> >); |
| static_assert(!CheckCommonWith<BadBasicCommonType, int>()); |
| |
| struct DullCommonType {}; |
| static_assert(!std::convertible_to<DullCommonType, int>); |
| |
| struct T1 {}; |
| static_assert(!std::convertible_to<DullCommonType, T1>); |
| |
| namespace std { |
| template <> |
| struct common_type<T1, int> { |
| using type = DullCommonType; |
| }; |
| |
| template <> |
| struct common_type<int, T1> { |
| using type = DullCommonType; |
| }; |
| } // namespace std |
| static_assert(HasValidCommonType<T1, int>()); |
| static_assert(!CheckCommonWith<T1, int>()); |
| |
| struct CommonTypeImplicitlyConstructibleFromInt { |
| explicit(false) CommonTypeImplicitlyConstructibleFromInt(int); |
| }; |
| static_assert(requires { |
| static_cast<CommonTypeImplicitlyConstructibleFromInt>(0); |
| }); |
| |
| struct T2 {}; |
| static_assert( |
| !std::convertible_to<CommonTypeImplicitlyConstructibleFromInt, T2>); |
| |
| namespace std { |
| template <> |
| struct common_type<T2, int> { |
| using type = CommonTypeImplicitlyConstructibleFromInt; |
| }; |
| |
| template <> |
| struct common_type<int, T2> { |
| using type = CommonTypeImplicitlyConstructibleFromInt; |
| }; |
| } // namespace std |
| static_assert(HasValidCommonType<T2, int>()); |
| static_assert(!CheckCommonWith<T2, int>()); |
| |
| struct CommonTypeExplicitlyConstructibleFromInt { |
| explicit CommonTypeExplicitlyConstructibleFromInt(int); |
| }; |
| static_assert(requires { |
| static_cast<CommonTypeExplicitlyConstructibleFromInt>(0); |
| }); |
| |
| struct T3 {}; |
| static_assert( |
| !std::convertible_to<CommonTypeExplicitlyConstructibleFromInt, T2>); |
| |
| namespace std { |
| template <> |
| struct common_type<T3, int> { |
| using type = CommonTypeExplicitlyConstructibleFromInt; |
| }; |
| |
| template <> |
| struct common_type<int, T3> { |
| using type = CommonTypeExplicitlyConstructibleFromInt; |
| }; |
| } // namespace std |
| static_assert(HasValidCommonType<T3, int>()); |
| static_assert(!CheckCommonWith<T3, int>()); |
| |
| struct T4 {}; |
| struct CommonTypeImplicitlyConstructibleFromT4 { |
| explicit(false) CommonTypeImplicitlyConstructibleFromT4(T4); |
| }; |
| static_assert(requires(T4 t4) { |
| static_cast<CommonTypeImplicitlyConstructibleFromT4>(t4); |
| }); |
| |
| namespace std { |
| template <> |
| struct common_type<T4, int> { |
| using type = CommonTypeImplicitlyConstructibleFromT4; |
| }; |
| |
| template <> |
| struct common_type<int, T4> { |
| using type = CommonTypeImplicitlyConstructibleFromT4; |
| }; |
| } // namespace std |
| static_assert(HasValidCommonType<T4, int>()); |
| static_assert(!CheckCommonWith<T4, int>()); |
| |
| struct T5 {}; |
| struct CommonTypeExplicitlyConstructibleFromT5 { |
| explicit CommonTypeExplicitlyConstructibleFromT5(T5); |
| }; |
| static_assert(requires(T5 t5) { |
| static_cast<CommonTypeExplicitlyConstructibleFromT5>(t5); |
| }); |
| |
| namespace std { |
| template <> |
| struct common_type<T5, int> { |
| using type = CommonTypeExplicitlyConstructibleFromT5; |
| }; |
| |
| template <> |
| struct common_type<int, T5> { |
| using type = CommonTypeExplicitlyConstructibleFromT5; |
| }; |
| } // namespace std |
| static_assert(HasValidCommonType<T5, int>()); |
| static_assert(!CheckCommonWith<T5, int>()); |
| |
| struct T6 {}; |
| struct CommonTypeNoCommonReference { |
| CommonTypeNoCommonReference(T6); |
| CommonTypeNoCommonReference(int); |
| }; |
| |
| namespace std { |
| template <> |
| struct common_type<T6, int> { |
| using type = CommonTypeNoCommonReference; |
| }; |
| |
| template <> |
| struct common_type<int, T6> { |
| using type = CommonTypeNoCommonReference; |
| }; |
| |
| template <> |
| struct common_type<T6&, int&> {}; |
| |
| template <> |
| struct common_type<int&, T6&> {}; |
| |
| template <> |
| struct common_type<T6&, const int&> {}; |
| |
| template <> |
| struct common_type<int&, const T6&> {}; |
| |
| template <> |
| struct common_type<T6&, volatile int&> {}; |
| |
| template <> |
| struct common_type<int&, volatile T6&> {}; |
| |
| template <> |
| struct common_type<T6&, const volatile int&> {}; |
| |
| template <> |
| struct common_type<int&, const volatile T6&> {}; |
| |
| template <> |
| struct common_type<const T6&, int&> {}; |
| |
| template <> |
| struct common_type<const int&, T6&> {}; |
| |
| template <> |
| struct common_type<const T6&, const int&> {}; |
| |
| template <> |
| struct common_type<const int&, const T6&> {}; |
| |
| template <> |
| struct common_type<const T6&, volatile int&> {}; |
| |
| template <> |
| struct common_type<const int&, volatile T6&> {}; |
| |
| template <> |
| struct common_type<const T6&, const volatile int&> {}; |
| |
| template <> |
| struct common_type<const int&, const volatile T6&> {}; |
| |
| template <> |
| struct common_type<volatile T6&, int&> {}; |
| |
| template <> |
| struct common_type<volatile int&, T6&> {}; |
| |
| template <> |
| struct common_type<volatile T6&, const int&> {}; |
| |
| template <> |
| struct common_type<volatile int&, const T6&> {}; |
| |
| template <> |
| struct common_type<volatile T6&, volatile int&> {}; |
| |
| template <> |
| struct common_type<volatile int&, volatile T6&> {}; |
| |
| template <> |
| struct common_type<volatile T6&, const volatile int&> {}; |
| |
| template <> |
| struct common_type<volatile int&, const volatile T6&> {}; |
| |
| template <> |
| struct common_type<const volatile T6&, int&> {}; |
| |
| template <> |
| struct common_type<const volatile int&, T6&> {}; |
| |
| template <> |
| struct common_type<const volatile T6&, const int&> {}; |
| |
| template <> |
| struct common_type<const volatile int&, const T6&> {}; |
| |
| template <> |
| struct common_type<const volatile T6&, volatile int&> {}; |
| |
| template <> |
| struct common_type<const volatile int&, volatile T6&> {}; |
| |
| template <> |
| struct common_type<const volatile T6&, const volatile int&> {}; |
| |
| template <> |
| struct common_type<const volatile int&, const volatile T6&> {}; |
| } // namespace std |
| |
| template <typename T, typename U> |
| constexpr bool HasCommonReference() noexcept { |
| return requires { typename std::common_reference_t<T, U>; }; |
| } |
| |
| static_assert(HasValidCommonType<T6, int>()); |
| static_assert(!HasCommonReference<const T6&, const int&>()); |
| static_assert(!CheckCommonWith<T6, int>()); |
| |
| struct T7 {}; |
| struct CommonTypeNoMetaCommonReference { |
| CommonTypeNoMetaCommonReference(T7); |
| CommonTypeNoMetaCommonReference(int); |
| }; |
| |
| namespace std { |
| template <> |
| struct common_type<T7, int> { |
| using type = CommonTypeNoMetaCommonReference; |
| }; |
| |
| template <> |
| struct common_type<int, T7> { |
| using type = CommonTypeNoMetaCommonReference; |
| }; |
| |
| template <> |
| struct common_type<T7&, int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<int&, T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<T7&, const int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<int&, const T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<T7&, volatile int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<int&, volatile T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<T7&, const volatile int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<int&, const volatile T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const T7&, int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const int&, T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const T7&, const int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const int&, const T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const T7&, volatile int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const int&, volatile T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const T7&, const volatile int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const int&, const volatile T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<volatile T7&, int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<volatile int&, T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<volatile T7&, const int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<volatile int&, const T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<volatile T7&, volatile int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<volatile int&, volatile T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<volatile T7&, const volatile int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<volatile int&, const volatile T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const volatile T7&, int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const volatile int&, T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const volatile T7&, const int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const volatile int&, const T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const volatile T7&, volatile int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const volatile int&, volatile T7&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const volatile T7&, const volatile int&> { |
| using type = void; |
| }; |
| |
| template <> |
| struct common_type<const volatile int&, const volatile T7&> { |
| using type = void; |
| }; |
| } // namespace std |
| static_assert(HasValidCommonType<T7, int>()); |
| static_assert(HasValidCommonType<const T7&, const int&>()); |
| static_assert(HasCommonReference<const T7&, const int&>()); |
| static_assert( |
| !HasCommonReference<std::common_type_t<T7, int>&, |
| std::common_reference_t<const T7&, const int&> >()); |
| static_assert(!CheckCommonWith<T7, int>()); |
| |
| struct CommonWithInt { |
| operator int() const volatile; |
| }; |
| |
| namespace std { |
| template <> |
| struct common_type<CommonWithInt, int> { |
| using type = int; |
| }; |
| |
| template <> |
| struct common_type<int, CommonWithInt> : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<CommonWithInt&, int&> : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<int&, CommonWithInt&> : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<CommonWithInt&, const int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<int&, const CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<CommonWithInt&, volatile int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<int&, volatile CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<CommonWithInt&, const volatile int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<int&, const volatile CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const CommonWithInt&, int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const int&, CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const CommonWithInt&, const int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const int&, const CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const CommonWithInt&, volatile int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const int&, volatile CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const CommonWithInt&, const volatile int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const int&, const volatile CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<volatile CommonWithInt&, int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<volatile int&, CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<volatile CommonWithInt&, const int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<volatile int&, const CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<volatile CommonWithInt&, volatile int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<volatile int&, volatile CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<volatile CommonWithInt&, const volatile int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<volatile int&, const volatile CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const volatile CommonWithInt&, int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const volatile int&, CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const volatile CommonWithInt&, const int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const volatile int&, const CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const volatile CommonWithInt&, volatile int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const volatile int&, volatile CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const volatile CommonWithInt&, const volatile int&> |
| : common_type<CommonWithInt, int> {}; |
| |
| template <> |
| struct common_type<const volatile int&, const volatile CommonWithInt&> |
| : common_type<CommonWithInt, int> {}; |
| } // namespace std |
| static_assert(CheckCommonWith<CommonWithInt, int>()); |
| |
| struct CommonWithIntButRefLong { |
| operator int() const volatile; |
| }; |
| |
| namespace std { |
| template <> |
| struct common_type<CommonWithIntButRefLong, int> { |
| using type = int; |
| }; |
| |
| template <> |
| struct common_type<int, CommonWithIntButRefLong> |
| : common_type<CommonWithIntButRefLong, int> {}; |
| |
| template <> |
| struct common_type<CommonWithIntButRefLong&, int&> { |
| using type = long; |
| }; |
| |
| template <> |
| struct common_type<int&, CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<CommonWithIntButRefLong&, const int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<int&, const CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<CommonWithIntButRefLong&, volatile int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<int&, volatile CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<CommonWithIntButRefLong&, const volatile int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<int&, const volatile CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const CommonWithIntButRefLong&, int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const int&, CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const CommonWithIntButRefLong&, const int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const int&, const CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const CommonWithIntButRefLong&, volatile int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const int&, volatile CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const CommonWithIntButRefLong&, const volatile int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const int&, const volatile CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<volatile CommonWithIntButRefLong&, int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<volatile int&, CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<volatile CommonWithIntButRefLong&, const int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<volatile int&, const CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<volatile CommonWithIntButRefLong&, volatile int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<volatile int&, volatile CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<volatile CommonWithIntButRefLong&, const volatile int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<volatile int&, const volatile CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const volatile CommonWithIntButRefLong&, int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const volatile int&, CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const volatile CommonWithIntButRefLong&, const int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const volatile int&, const CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const volatile CommonWithIntButRefLong&, volatile int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const volatile int&, volatile CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const volatile CommonWithIntButRefLong&, const volatile int&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| |
| template <> |
| struct common_type<const volatile int&, const volatile CommonWithIntButRefLong&> |
| : common_type<CommonWithIntButRefLong&, int&> {}; |
| } // namespace std |
| static_assert(CheckCommonWith<CommonWithIntButRefLong, int>()); |
| |
| int main(int, char**) { return 0; } |