mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 09:06:07 +00:00
[libcxx][type_traits] Add C++20 changes to common_type
Summary: This already implements the expected changes for LWG-3205 Reviewers: mclow.lists, EricWF, CaseyCarter, cjdb, #libc, ldionne Reviewed By: #libc, ldionne Subscribers: dexonsmith, broadwaylamb, christof, ldionne, libcxx-commits Tags: #libc Differential Revision: https://reviews.llvm.org/D74350
This commit is contained in:
parent
a675c1dee4
commit
c579ab9962
@ -2348,9 +2348,33 @@ struct _LIBCPP_TEMPLATE_VIS make_unsigned
|
||||
template <class _Tp> using make_unsigned_t = typename make_unsigned<_Tp>::type;
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
template <class...> using void_t = void;
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
// Let COND_RES(X, Y) be:
|
||||
template <class _Tp, class _Up>
|
||||
using __cond_type = decltype(false ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>());
|
||||
|
||||
template <class _Tp, class _Up, class = void>
|
||||
struct __common_type3 {};
|
||||
|
||||
// sub-bullet 4 - "if COND_RES(CREF(D1), CREF(D2)) denotes a type..."
|
||||
template <class _Tp, class _Up>
|
||||
struct __common_type3<_Tp, _Up, void_t<__cond_type<const _Tp&, const _Up&>>>
|
||||
{
|
||||
using type = remove_cvref_t<__cond_type<const _Tp&, const _Up&>>;
|
||||
};
|
||||
|
||||
template <class _Tp, class _Up, class = void>
|
||||
struct __common_type2_imp : __common_type3<_Tp, _Up> {};
|
||||
#else
|
||||
template <class _Tp, class _Up, class = void>
|
||||
struct __common_type2_imp {};
|
||||
#endif
|
||||
|
||||
// sub-bullet 3 - "if decay_t<decltype(false ? declval<D1>() : declval<D2>())> ..."
|
||||
template <class _Tp, class _Up>
|
||||
struct __common_type2_imp<_Tp, _Up,
|
||||
typename __void_t<decltype(
|
||||
@ -2414,6 +2438,7 @@ struct _LIBCPP_TEMPLATE_VIS common_type<_Tp>
|
||||
|
||||
// bullet 3 - sizeof...(Tp) == 2
|
||||
|
||||
// sub-bullet 1 - "If is_same_v<T1, D1> is false or ..."
|
||||
template <class _Tp, class _Up>
|
||||
struct _LIBCPP_TEMPLATE_VIS common_type<_Tp, _Up>
|
||||
: conditional<
|
||||
@ -4296,8 +4321,6 @@ struct __has_operator_addressof
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
|
||||
template <class...> using void_t = void;
|
||||
|
||||
template <class... _Args>
|
||||
struct conjunction : _And<_Args...> {};
|
||||
template<class... _Args>
|
||||
|
@ -24,6 +24,13 @@ struct X { explicit X(T const&){} };
|
||||
template <class T>
|
||||
struct S { explicit S(T const&){} };
|
||||
|
||||
template <class T>
|
||||
struct bad_reference_wrapper {
|
||||
bad_reference_wrapper(T&);
|
||||
bad_reference_wrapper(T&&) = delete;
|
||||
operator T&() const;
|
||||
};
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename T>
|
||||
@ -95,13 +102,16 @@ struct TernaryOp {
|
||||
>::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<T0>.
|
||||
// (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<T0, T0>; otherwise there shall be no member type.
|
||||
void test_bullet_two() {
|
||||
static_assert((std::is_same<std::common_type<void>::type, void>::value), "");
|
||||
static_assert((std::is_same<std::common_type<int>::type, int>::value), "");
|
||||
@ -122,11 +132,11 @@ void test_bullet_three_one_imp() {
|
||||
static_assert((std::is_same<typename std::common_type<T, U>::type, typename std::common_type<DT, DU>::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<T1> and decay_t<T2>, respectively.
|
||||
// (3.3.1)
|
||||
// (4.3.1)
|
||||
// -- If is_same_v<T1, D1> is false or is_same_v<T2, D2> is false, let C
|
||||
// denote the same type, if any, as common_type_t<D1, D2>.
|
||||
void test_bullet_three_one() {
|
||||
@ -160,16 +170,19 @@ void test_bullet_three_one() {
|
||||
}
|
||||
}
|
||||
|
||||
// (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<T1> and decay_t<T2>, 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<decltype(false ? declval<D1>() : declval<D2>())>
|
||||
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 @@ void test_bullet_three_two() {
|
||||
}
|
||||
}
|
||||
|
||||
// (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<T1> and decay_t<T2>, 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<COND-RES(CREF(D1), CREF(D2))>.
|
||||
void test_bullet_three_four() {
|
||||
#if TEST_STD_VER >= 20
|
||||
static_assert(std::is_same_v<std::common_type_t<int, bad_reference_wrapper<int>>, int>, "");
|
||||
static_assert(std::is_same_v<std::common_type_t<bad_reference_wrapper<double>, double>, double>, "");
|
||||
static_assert(std::is_same_v<std::common_type_t<const bad_reference_wrapper<double>, double>, double>, "");
|
||||
static_assert(std::is_same_v<std::common_type_t<volatile bad_reference_wrapper<double>, double>, double>, "");
|
||||
static_assert(std::is_same_v<std::common_type_t<const volatile bad_reference_wrapper<double>, double>, double>, "");
|
||||
|
||||
static_assert(std::is_same_v<std::common_type_t<bad_reference_wrapper<double>, const double>, double>, "");
|
||||
static_assert(std::is_same_v<std::common_type_t<bad_reference_wrapper<double>, volatile double>, double>, "");
|
||||
static_assert(std::is_same_v<std::common_type_t<bad_reference_wrapper<double>, const volatile double>, double>, "");
|
||||
|
||||
static_assert(std::is_same_v<std::common_type_t<bad_reference_wrapper<double>&, double>, double>, "");
|
||||
static_assert(std::is_same_v<std::common_type_t<bad_reference_wrapper<double>, 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<T1, T2>. If there is
|
||||
@ -307,7 +350,8 @@ int main(int, char**)
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user