[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