diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -2348,9 +2348,33 @@ template using make_unsigned_t = typename make_unsigned<_Tp>::type; #endif +#if _LIBCPP_STD_VER > 14 +template using void_t = void; +#endif + +#if _LIBCPP_STD_VER > 17 +// Let COND_RES(X, Y) be: +template +using __cond_type = decltype(false ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>()); + +template +struct __common_type3 {}; + +// sub-bullet 4 - "if COND_RES(CREF(D1), CREF(D2)) denotes a type..." +template +struct __common_type3<_Tp, _Up, void_t<__cond_type>> +{ + using type = remove_cvref_t<__cond_type>; +}; + +template +struct __common_type2_imp : __common_type3<_Tp, _Up> {}; +#else template struct __common_type2_imp {}; +#endif +// sub-bullet 3 - "if decay_t() : declval())> ..." template struct __common_type2_imp<_Tp, _Up, typename __void_t is false or ..." template struct _LIBCPP_TEMPLATE_VIS common_type<_Tp, _Up> : conditional< @@ -4296,8 +4321,6 @@ #if _LIBCPP_STD_VER > 14 -template using void_t = void; - template struct conjunction : _And<_Args...> {}; template diff --git a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp --- a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp @@ -24,6 +24,13 @@ template struct S { explicit S(T const&){} }; +template +struct bad_reference_wrapper { + bad_reference_wrapper(T&); + bad_reference_wrapper(T&&) = delete; + operator T&() const; +}; + namespace std { template @@ -95,13 +102,16 @@ >::type type; }; +// (4.1) // -- If sizeof...(T) is zero, there shall be no member type. void test_bullet_one() { static_assert(no_common_type<>::value, ""); } -// If sizeof...(T) is one, let T0 denote the sole type constituting the pack T. -// The member typedef-name type shall denote the same type as decay_t. +// (4.2) +// -- If sizeof...(T) is one, let T0 denote the sole type constituting the pack +// T. The member typedef-name type shall denote the same type, if any, as +// common_type_t; otherwise there shall be no member type. void test_bullet_two() { static_assert((std::is_same::type, void>::value), ""); static_assert((std::is_same::type, int>::value), ""); @@ -122,11 +132,11 @@ static_assert((std::is_same::type, typename std::common_type::type>::value), ""); } -// (3.3) +// (4.3) // -- If sizeof...(T) is two, let the first and second types constituting T be // denoted by T1 and T2, respectively, and let D1 and D2 denote the same types // as decay_t and decay_t, respectively. -// (3.3.1) +// (4.3.1) // -- If is_same_v is false or is_same_v is false, let C // denote the same type, if any, as common_type_t. void test_bullet_three_one() { @@ -160,16 +170,19 @@ } } -// (3.3) +// (4.3) // -- If sizeof...(T) is two, let the first and second types constituting T be // denoted by T1 and T2, respectively, and let D1 and D2 denote the same types // as decay_t and decay_t, respectively. -// (3.3.1) +// (4.3.1) // -- If [...] -// (3.3.2) -// -- Otherwise, let C denote the same type, if any, as +// (4.3.2) +// -- [Note: [...] +// (4.3.3) +// -- Otherwise, if // decay_t() : declval())> -void test_bullet_three_two() { +// denotes a type, let C denote that type. +void test_bullet_three_three() { { typedef int const* T1; typedef int* T2; @@ -200,7 +213,37 @@ } } -// (3.4) +// (4.3) +// -- If sizeof...(T) is two, let the first and second types constituting T be +// denoted by T1 and T2, respectively, and let D1 and D2 denote the same types +// as decay_t and decay_t, respectively. +// (4.3.1) +// -- If [...] +// (4.3.2) +// -- [Note: [...] +// (4.3.3) +// -- Otherwise +// (4.3.4) +// -- Otherwise, if COND-RES(CREF(D1), CREF(D2)) denotes a type, let C +// denote the type decay_t. +void test_bullet_three_four() { +#if TEST_STD_VER >= 20 + static_assert(std::is_same_v>, int>, ""); + static_assert(std::is_same_v, double>, double>, ""); + static_assert(std::is_same_v, double>, double>, ""); + static_assert(std::is_same_v, double>, double>, ""); + static_assert(std::is_same_v, double>, double>, ""); + + static_assert(std::is_same_v, const double>, double>, ""); + static_assert(std::is_same_v, volatile double>, double>, ""); + static_assert(std::is_same_v, const volatile double>, double>, ""); + + static_assert(std::is_same_v&, double>, double>, ""); + static_assert(std::is_same_v, double&>, double>, ""); +#endif +} + +// (4.4) // -- If sizeof...(T) is greater than two, let T1, T2, and R, respectively, // denote the first, second, and (pack of) remaining types constituting T. // Let C denote the same type, if any, as common_type_t. If there is @@ -307,7 +350,8 @@ test_bullet_one(); test_bullet_two(); test_bullet_three_one(); - test_bullet_three_two(); + test_bullet_three_three(); + test_bullet_three_four(); test_bullet_four(); // P0548