[libcxx-commits] [libcxx] 311207b - [libc++][P2321R2] Add specializations of basic_common_reference and common_type for tuple

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jan 17 10:51:33 PST 2022


Author: Nikolas Klauser
Date: 2022-01-17T19:49:57+01:00
New Revision: 311207bbea2b109ca6e40426bebe76a5f9786315

URL: https://github.com/llvm/llvm-project/commit/311207bbea2b109ca6e40426bebe76a5f9786315
DIFF: https://github.com/llvm/llvm-project/commit/311207bbea2b109ca6e40426bebe76a5f9786315.diff

LOG: [libc++][P2321R2] Add specializations of basic_common_reference and common_type for tuple

Add specializations of `basic_common_reference` and `common_type` for `tuple`

Reviewed By: ldionne, Mordante, #libc

Spies: libcxx-commits

Differential Revision: https://reviews.llvm.org/D116538

Added: 
    

Modified: 
    libcxx/docs/Status/Cxx2bPapers.csv
    libcxx/include/tuple
    libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp
    libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv
index 93b2d6befff94..f5ab6edad9eaa 100644
--- a/libcxx/docs/Status/Cxx2bPapers.csv
+++ b/libcxx/docs/Status/Cxx2bPapers.csv
@@ -33,7 +33,7 @@
 "`P2077R3 <https://wg21.link/P2077R3>`__","LWG","Heterogeneous erasure overloads for associative containers","October 2021","",""
 "`P2251R1 <https://wg21.link/P2251R1>`__","LWG","Require ``span`` & ``basic_string_view`` to be Trivially Copyable","October 2021","|Complete|","14.0"
 "`P2301R1 <https://wg21.link/P2301R1>`__","LWG","Add a ``pmr`` alias for ``std::stacktrace``","October 2021","",""
-"`P2321R2 <https://wg21.link/P2321R2>`__","LWG","``zip``","October 2021","",""
+"`P2321R2 <https://wg21.link/P2321R2>`__","LWG","``zip``","October 2021","|In Progress|",""
 "`P2340R1 <https://wg21.link/P2340R1>`__","LWG","Clarifying the status of the 'C headers'","October 2021","",""
 "`P2393R1 <https://wg21.link/P2393R1>`__","LWG","Cleaning up ``integer``-class types","October 2021","",""
 "`P2401R0 <https://wg21.link/P2401R0>`__","LWG","Add a conditional ``noexcept`` specification to ``std::exchange``","October 2021","|Complete|","14.0"

diff  --git a/libcxx/include/tuple b/libcxx/include/tuple
index 8ee5c2eef51df..5cf120fec359e 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -73,6 +73,19 @@ public:
     void swap(tuple&) noexcept(AND(swap(declval<T&>(), declval<T&>())...));               // constexpr in C++20
 };
 
+
+template<class... TTypes, class... UTypes, template<class> class TQual, template<class> class UQual> // since C++23
+  requires requires { typename tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...>; }
+struct basic_common_reference<tuple<TTypes...>, tuple<UTypes...>, TQual, UQual> {
+  using type = tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...>;
+};
+
+template<class... TTypes, class... UTypes>                                // since C++23
+  requires requires { typename tuple<common_type_t<TTypes, UTypes>...>; }
+struct common_type<tuple<TTypes...>, tuple<UTypes...>> {
+  using type = tuple<common_type_t<TTypes, UTypes>...>;
+};
+
 template <class ...T>
 tuple(T...) -> tuple<T...>;                                         // since C++17
 template <class T1, class T2>
@@ -1103,7 +1116,21 @@ public:
     void swap(tuple&) _NOEXCEPT {}
 };
 
-#if _LIBCPP_STD_VER >= 17
+#if _LIBCPP_STD_VER > 20
+template <class... _TTypes, class... _UTypes, template<class> class _TQual, template<class> class _UQual>
+    requires requires { typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; }
+struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual> {
+    using type = tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>;
+};
+
+template <class... _TTypes, class... _UTypes>
+    requires requires { typename tuple<common_type_t<_TTypes, _UTypes>...>; }
+struct common_type<tuple<_TTypes...>, tuple<_UTypes...>> {
+    using type = tuple<common_type_t<_TTypes, _UTypes>...>;
+};
+#endif
+
+#if _LIBCPP_STD_VER > 14
 template <class ..._Tp>
 tuple(_Tp...) -> tuple<_Tp...>;
 template <class _Tp1, class _Tp2>

diff  --git a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp
index b18afddd5c41c..17421c17f1dee 100644
--- a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp
@@ -13,8 +13,11 @@
 // type_traits
 // common_reference
 
+#include <tuple>
 #include <type_traits>
 
+#include "test_macros.h"
+
 template <class T>
 constexpr bool has_type = requires {
   typename T::type;
@@ -22,19 +25,19 @@ constexpr bool has_type = requires {
 
 // A slightly simplified variation of std::tuple
 template <class...>
-struct Tuple {};
+struct UserTuple {};
 
 template <class, class, class>
 struct Tuple_helper {};
 template <class... Ts, class... Us>
-struct Tuple_helper<std::void_t<std::common_reference_t<Ts, Us>...>, Tuple<Ts...>, Tuple<Us...> > {
-  using type = Tuple<std::common_reference_t<Ts, Us>...>;
+struct Tuple_helper<std::void_t<std::common_reference_t<Ts, Us>...>, UserTuple<Ts...>, UserTuple<Us...> > {
+  using type = UserTuple<std::common_reference_t<Ts, Us>...>;
 };
 
 namespace std {
 template <class... Ts, class... Us, template <class> class TQual, template <class> class UQual>
-struct basic_common_reference< ::Tuple<Ts...>, ::Tuple<Us...>, TQual, UQual>
-    : ::Tuple_helper<void, Tuple<TQual<Ts>...>, Tuple<UQual<Us>...> > {};
+struct basic_common_reference< ::UserTuple<Ts...>, ::UserTuple<Us...>, TQual, UQual>
+    : ::Tuple_helper<void, UserTuple<TQual<Ts>...>, UserTuple<UQual<Us>...> > {};
 } // namespace std
 
 struct X2 {};
@@ -107,11 +110,11 @@ static_assert(std::is_same_v<std::common_reference_t<int const (&)[10], int vola
 //    -- Otherwise, if basic_common_reference<remove_cvref_t<T1>,
 //       remove_cvref_t<T2>, XREF(T1), XREF(T2)>::type is well-formed, then the
 //       member typedef type denotes that type.
-static_assert(std::is_same_v<std::common_reference_t<const Tuple<int, short>&, Tuple<int&, short volatile&>>,
-                             Tuple<const int&, const volatile short&>>);
+static_assert(std::is_same_v<std::common_reference_t<const UserTuple<int, short>&, UserTuple<int&, short volatile&>>,
+                             UserTuple<const int&, const volatile short&>>);
 
-static_assert(std::is_same_v<std::common_reference_t<volatile Tuple<int, short>&, const Tuple<int, short>&>,
-                             const volatile Tuple<int, short>&>);
+static_assert(std::is_same_v<std::common_reference_t<volatile UserTuple<int, short>&, const UserTuple<int, short>&>,
+                             const volatile UserTuple<int, short>&>);
 
 // (6.3.3)
 //    -- Otherwise, if COND_RES(T1, T2) is well-formed, then the member typedef
@@ -152,7 +155,7 @@ static_assert(std::is_same_v<std::common_reference_t<X2&, Y2 const&>, Z2>);
 
 // (6.3.5)
 //    -- Otherwise, there shall be no member type.
-static_assert(!has_type<std::common_reference<volatile Tuple<short>&, const Tuple<int, short>&> >);
+static_assert(!has_type<std::common_reference<volatile UserTuple<short>&, const UserTuple<int, short>&> >);
 
 // (6.4)
 //  -- Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest,
@@ -169,4 +172,31 @@ static_assert(std::is_same_v<std::common_reference_t<int&&, int const&, float&>,
 //    -- Otherwise, there shall be no member type.
 static_assert(!has_type<std::common_reference<int, short, int, char*> >);
 
+#if TEST_STD_VER > 20
+static_assert(std::is_same_v<std::common_reference_t<std::tuple<int, int>>, std::tuple<int, int>>);
+static_assert(std::is_same_v<std::common_reference_t<std::tuple<int, long>, std::tuple<long, int>>, std::tuple<long, long>>);
+static_assert(std::is_same_v<std::common_reference_t<std::tuple<int&, const int&>, std::tuple<const int&, int>>,
+                             std::tuple<const int&, int>>);
+static_assert(std::is_same_v<std::common_reference_t<std::tuple<int&, volatile int&>, std::tuple<volatile int&, int>>,
+                             std::tuple<volatile int&, int>>);
+static_assert(std::is_same_v<std::common_reference_t<std::tuple<int&, const volatile int&>, std::tuple<const volatile int&, int>>,
+                             std::tuple<const volatile int&, int>>);
+static_assert(!has_type<std::common_reference_t<std::tuple<const int&, volatile int&>, std::tuple<volatile int&, const int&>>>);
+
+static_assert(std::is_same_v<std::common_reference_t<std::tuple<int, X2>, std::tuple<int, Y2>>, std::tuple<int, Z2>>);
+static_assert(std::is_same_v<std::common_reference_t<std::tuple<int, X2>, std::tuple<int, Y2>>, std::tuple<int, Z2>>);
+static_assert(!has_type<std::common_reference<std::tuple<int, const X2>, std::tuple<float, const Z2>>>);
+static_assert(!has_type<std::common_reference<std::tuple<int, X2>, std::tuple<float, Z2>>>);
+static_assert(!has_type<std::common_reference<std::tuple<int, X2>, int, X2>>);
+
+struct A {};
+template <template<class> class TQual, template<class> class UQual>
+struct std::basic_common_reference<A, std::tuple<B>, TQual, UQual> {
+  using type = tuple<UQual<B>>;
+};
+
+static_assert(std::is_same_v<std::common_reference_t<A, std::tuple<B>,std::tuple<D>>, std::tuple<B>>);
+
+#endif
+
 int main(int, char**) { return 0; }

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 f070b2770d0a0..901443a2c4bd2 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
@@ -12,6 +12,7 @@
 
 #include <functional>
 #include <memory>
+#include <tuple>
 #include <type_traits>
 
 #include "test_macros.h"
@@ -261,6 +262,16 @@ void test_bullet_four() {
   }
 }
 
+#if TEST_STD_VER > 20
+struct A {};
+struct B {};
+struct C : B {};
+template<>
+struct std::common_type<A, std::tuple<B>> {
+  using type = tuple<B>;
+};
+#endif
+
 int main(int, char**)
 {
     static_assert((std::is_same<std::common_type<int>::type, int>::value), "");
@@ -321,7 +332,7 @@ int main(int, char**)
   test_bullet_three_four();
   test_bullet_four();
 
-//  P0548
+    // P0548
     static_assert((std::is_same<std::common_type<S<int> >::type,         S<int> >::value), "");
     static_assert((std::is_same<std::common_type<S<int>, S<int> >::type, S<int> >::value), "");
 
@@ -340,5 +351,16 @@ int main(int, char**)
     static_assert(std::is_same<std::common_type<int, int, int, int, int, int, int, int>::type, int>::value, "");
 #endif
 
+#if TEST_STD_VER > 20
+    // P2321
+    static_assert(std::is_same_v<std::common_type_t<std::tuple<int>>, std::tuple<int>>);
+    static_assert(std::is_same_v<std::common_type_t<std::tuple<int>, std::tuple<long>>, std::tuple<long>>);
+    static_assert(std::is_same_v<std::common_type_t<std::tuple<const int>, std::tuple<const int>>, std::tuple<int>>);
+    static_assert(std::is_same_v<std::common_type_t<std::tuple<const int&>>, std::tuple<int>>);
+    static_assert(std::is_same_v<std::common_type_t<std::tuple<const volatile int&>, std::tuple<const volatile long&>>, std::tuple<long>>);
+
+    static_assert(std::is_same_v<std::common_reference_t<A, std::tuple<B>,std::tuple<C>>, std::tuple<B>>);
+#endif
+
   return 0;
 }


        


More information about the libcxx-commits mailing list