[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