diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -33,7 +33,7 @@ "`P2077R3 `__","LWG","Heterogeneous erasure overloads for associative containers","October 2021","","" "`P2251R1 `__","LWG","Require ``span`` & ``basic_string_view`` to be Trivially Copyable","October 2021","|Complete|","14.0" "`P2301R1 `__","LWG","Add a ``pmr`` alias for ``std::stacktrace``","October 2021","","" -"`P2321R2 `__","LWG","``zip``","October 2021","","" +"`P2321R2 `__","LWG","``zip``","October 2021","|In Progress|","" "`P2340R1 `__","LWG","Clarifying the status of the 'C headers'","October 2021","","" "`P2393R1 `__","LWG","Cleaning up ``integer``-class types","October 2021","","" "`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 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -73,6 +73,19 @@ void swap(tuple&) noexcept(AND(swap(declval(), declval())...)); // constexpr in C++20 }; + +template class TQual, template class UQual> // since C++23 + requires requires { typename tuple, UQual>...>; } +struct basic_common_reference, tuple, TQual, UQual> { + using type = tuple, UQual>...>; +}; + +template // since C++23 + requires requires { typename tuple...>; } +struct common_type, tuple> { + using type = tuple...>; +}; + template tuple(T...) -> tuple; // since C++17 template @@ -1103,7 +1116,21 @@ void swap(tuple&) _NOEXCEPT {} }; -#if _LIBCPP_STD_VER >= 17 +#if _LIBCPP_STD_VER > 20 +template class _TQual, template class _UQual> + requires requires { typename tuple, _UQual<_UTypes>>...>; } +struct basic_common_reference, tuple<_UTypes...>, _TQual, _UQual> { + using type = tuple, _UQual<_UTypes>>...>; +}; + +template + requires requires { typename tuple...>; } +struct common_type, tuple<_UTypes...>> { + using type = tuple...>; +}; +#endif + +#if _LIBCPP_STD_VER > 14 template tuple(_Tp...) -> tuple<_Tp...>; template 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 --- 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 #include +#include "test_macros.h" + template constexpr bool has_type = requires { typename T::type; @@ -22,19 +25,19 @@ // A slightly simplified variation of std::tuple template -struct Tuple {}; +struct UserTuple {}; template struct Tuple_helper {}; template -struct Tuple_helper...>, Tuple, Tuple > { - using type = Tuple...>; +struct Tuple_helper...>, UserTuple, UserTuple > { + using type = UserTuple...>; }; namespace std { template class TQual, template class UQual> -struct basic_common_reference< ::Tuple, ::Tuple, TQual, UQual> - : ::Tuple_helper...>, Tuple...> > {}; +struct basic_common_reference< ::UserTuple, ::UserTuple, TQual, UQual> + : ::Tuple_helper...>, UserTuple...> > {}; } // namespace std struct X2 {}; @@ -107,11 +110,11 @@ // -- Otherwise, if basic_common_reference, // remove_cvref_t, XREF(T1), XREF(T2)>::type is well-formed, then the // member typedef type denotes that type. -static_assert(std::is_same_v&, Tuple>, - Tuple>); +static_assert(std::is_same_v&, UserTuple>, + UserTuple>); -static_assert(std::is_same_v&, const Tuple&>, - const volatile Tuple&>); +static_assert(std::is_same_v&, const UserTuple&>, + const volatile UserTuple&>); // (6.3.3) // -- Otherwise, if COND_RES(T1, T2) is well-formed, then the member typedef @@ -152,7 +155,7 @@ // (6.3.5) // -- Otherwise, there shall be no member type. -static_assert(!has_type&, const Tuple&> >); +static_assert(!has_type&, const UserTuple&> >); // (6.4) // -- Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest, @@ -169,4 +172,31 @@ // -- Otherwise, there shall be no member type. static_assert(!has_type >); +#if TEST_STD_VER > 20 +static_assert(std::is_same_v>, std::tuple>); +static_assert(std::is_same_v, std::tuple>, std::tuple>); +static_assert(std::is_same_v, std::tuple>, + std::tuple>); +static_assert(std::is_same_v, std::tuple>, + std::tuple>); +static_assert(std::is_same_v, std::tuple>, + std::tuple>); +static_assert(!has_type, std::tuple>>); + +static_assert(std::is_same_v, std::tuple>, std::tuple>); +static_assert(std::is_same_v, std::tuple>, std::tuple>); +static_assert(!has_type, std::tuple>>); +static_assert(!has_type, std::tuple>>); +static_assert(!has_type, int, X2>>); + +struct A {}; +template class TQual, template class UQual> +struct std::basic_common_reference, TQual, UQual> { + using type = tuple>; +}; + +static_assert(std::is_same_v,std::tuple>, std::tuple>); + +#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 --- 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 #include +#include #include #include "test_macros.h" @@ -261,6 +262,16 @@ } } +#if TEST_STD_VER > 20 +struct A {}; +struct B {}; +struct C : B {}; +template<> +struct std::common_type> { + using type = tuple; +}; +#endif + int main(int, char**) { static_assert((std::is_same::type, int>::value), ""); @@ -321,7 +332,7 @@ test_bullet_three_four(); test_bullet_four(); -// P0548 + // P0548 static_assert((std::is_same >::type, S >::value), ""); static_assert((std::is_same, S >::type, S >::value), ""); @@ -340,5 +351,16 @@ static_assert(std::is_same::type, int>::value, ""); #endif +#if TEST_STD_VER > 20 + // P2321 + static_assert(std::is_same_v>, std::tuple>); + static_assert(std::is_same_v, std::tuple>, std::tuple>); + static_assert(std::is_same_v, std::tuple>, std::tuple>); + static_assert(std::is_same_v>, std::tuple>); + static_assert(std::is_same_v, std::tuple>, std::tuple>); + + static_assert(std::is_same_v,std::tuple>, std::tuple>); +#endif + return 0; }