[libcxx-commits] [libcxx] c579ab9 - [libcxx][type_traits] Add C++20 changes to common_type
Michael Schellenberger Costa via libcxx-commits
libcxx-commits at lists.llvm.org
Mon May 18 05:06:40 PDT 2020
Author: Michael Schellenberger Costa
Date: 2020-05-18T14:06:32+02:00
New Revision: c579ab9962b10d275ebd951657414a479bd7acab
URL: https://github.com/llvm/llvm-project/commit/c579ab9962b10d275ebd951657414a479bd7acab
DIFF: https://github.com/llvm/llvm-project/commit/c579ab9962b10d275ebd951657414a479bd7acab.diff
LOG: [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
Added:
Modified:
libcxx/include/type_traits
libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index ece46436a783..be031037d676 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -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>
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
index a6b2f6244a2e..e4668b08d1d6 100644
--- 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 @@ 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
More information about the libcxx-commits
mailing list