From 9d88b1741ba5f5a3b413f247174a791ea8f26d33 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Mon, 20 Oct 2025 15:56:24 +0800 Subject: [PATCH] [libc++] P2255R2: Add deleted `pair` constructor overloads Implements parts for `std::pair` from P2255R2 "A type trait to detect reference binding to temporary". --- libcxx/docs/Status/Cxx23Papers.csv | 2 +- libcxx/include/__utility/pair.h | 77 +++++- .../flat.map/flat.map.observers/comp.pass.cpp | 2 +- .../flat.multimap.observers/comp.pass.cpp | 2 +- .../pairs/pairs.pair/ctor.U_V.pass.cpp | 12 +- .../pairs/pairs.pair/ctor.deleted.verify.cpp | 229 ++++++++++++++++++ .../ctor.pair_U_V_const_move.pass.cpp | 8 + .../ctor.pair_U_V_const_ref.pass.cpp | 13 +- .../pairs.pair/ctor.pair_U_V_move.pass.cpp | 10 + .../pairs.pair/ctor.pair_U_V_ref.pass.cpp | 8 + .../pairs/pairs.pair/ctor.pair_like.pass.cpp | 46 ++++ 11 files changed, 396 insertions(+), 13 deletions(-) create mode 100644 libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.deleted.verify.cpp diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index 3a87e64339e1f..030f85e1315ab 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -43,7 +43,7 @@ "`P0627R6 `__","Function to mark unreachable code","2022-02 (Virtual)","|Complete|","15","`#105175 `__","" "`P1206R7 `__","``ranges::to``: A function to convert any range to a container","2022-02 (Virtual)","|Complete|","17","`#105176 `__","" "`P1413R3 `__","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","2022-02 (Virtual)","|Complete|","","`#105177 `__","``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but clang doesn't issue a diagnostic for deprecated using template declarations." -"`P2255R2 `__","A type trait to detect reference binding to temporary","2022-02 (Virtual)","|Partial|","","`#105180 `__","Implemented the type traits only." +"`P2255R2 `__","A type trait to detect reference binding to temporary","2022-02 (Virtual)","|Partial|","","`#105180 `__","Implemented the type traits and changes to ``std::pair`` only." "`P2273R3 `__","Making ``std::unique_ptr`` constexpr","2022-02 (Virtual)","|Complete|","16","`#105182 `__","" "`P2387R3 `__","Pipe support for user-defined range adaptors","2022-02 (Virtual)","|Complete|","19","`#105183 `__","" "`P2440R1 `__","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","2022-02 (Virtual)","|Partial|","","`#105184 `__","Only ``ranges::iota`` is implemented." diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h index 33694c52430f1..335757e378841 100644 --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -16,6 +16,7 @@ #include <__config> #include <__cstddef/size_t.h> #include <__fwd/array.h> +#include <__fwd/complex.h> #include <__fwd/pair.h> #include <__fwd/tuple.h> #include <__tuple/tuple_like_no_subrange.h> @@ -36,6 +37,7 @@ #include <__type_traits/is_swappable.h> #include <__type_traits/is_trivially_relocatable.h> #include <__type_traits/nat.h> +#include <__type_traits/reference_constructs_from_temporary.h> #include <__type_traits/unwrap_ref.h> #include <__utility/declval.h> #include <__utility/forward.h> @@ -68,9 +70,23 @@ struct __check_pair_construction { template static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_pair_constructible() { +# if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + return is_constructible_v<_T1, _U1> && is_constructible_v<_T2, _U2> && + !reference_constructs_from_temporary_v<_T1, _U1&&> && !reference_constructs_from_temporary_v<_T2, _U2&&>; +# else return is_constructible<_T1, _U1>::value && is_constructible<_T2, _U2>::value; +# endif } +# if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + template + static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_pair_constructor_deleted() { + return is_constructible_v<_T1, _U1> && is_constructible_v<_T2, _U2> && + (reference_constructs_from_temporary_v<_T1, _U1&&> || reference_constructs_from_temporary_v<_T2, _U2&&>); + return is_constructible<_T1, _U1>::value && is_constructible<_T2, _U2>::value; + } +# endif + template static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_implicit() { return is_convertible<_U1, _T1>::value && is_convertible<_U2, _T2>::value; @@ -157,14 +173,20 @@ struct pair class _U1, class _U2, # endif - __enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1, _U2>(), int> = 0 > + __enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1&&, _U2&&>(), int> = 0 > _LIBCPP_HIDE_FROM_ABI - _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1, _U2>()) + _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1&&, _U2&&>()) pair(_U1&& __u1, _U2&& __u2) noexcept(is_nothrow_constructible::value && is_nothrow_constructible::value) : first(std::forward<_U1>(__u1)), second(std::forward<_U2>(__u2)) { } +# if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + template + requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted<_U1 &&, _U2 &&>()) + explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1&&, _U2&&>()) pair(_U1&&, _U2&&) = delete; +# endif + # if _LIBCPP_STD_VER >= 23 template & __p) noexcept((is_nothrow_constructible::value && is_nothrow_constructible::value)) : first(__p.first), second(__p.second) {} + +# if __has_builtin(__reference_constructs_from_temporary) + template + requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted<_U1&, _U2&>()) + explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1&, _U2&>()) pair(pair<_U1, _U2>&) = delete; +# endif # endif template < @@ -186,15 +214,30 @@ struct pair is_nothrow_constructible::value) : first(__p.first), second(__p.second) {} - template ::template __is_pair_constructible<_U1, _U2>(), int> = 0> +# if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + template + requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted()) + explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit()) + pair(const pair<_U1, _U2>&) = delete; +# endif + + template < + class _U1, + class _U2, + __enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1&&, _U2&&>(), int> = 0> _LIBCPP_HIDE_FROM_ABI - _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1, _U2>()) + _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1&&, _U2&&>()) pair(pair<_U1, _U2>&& __p) noexcept(is_nothrow_constructible::value && is_nothrow_constructible::value) : first(std::forward<_U1>(__p.first)), second(std::forward<_U2>(__p.second)) {} +# if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + template + requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted<_U1 &&, _U2 &&>()) + explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1&&, _U2&&>()) + pair(pair<_U1, _U2>&&) = delete; +# endif + # if _LIBCPP_STD_VER >= 23 template < class _U1, @@ -206,16 +249,34 @@ struct pair pair(const pair<_U1, _U2>&& __p) noexcept(is_nothrow_constructible::value && is_nothrow_constructible::value) : first(std::move(__p.first)), second(std::move(__p.second)) {} + +# if __has_builtin(__reference_constructs_from_temporary) + template + requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted()) + explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit()) + pair(const pair<_U1, _U2>&&) = delete; +# endif # endif # if _LIBCPP_STD_VER >= 23 template <__pair_like_no_subrange _PairLike> - requires(is_constructible_v(std::declval<_PairLike &&>()))> && - is_constructible_v(std::declval<_PairLike &&>()))>) + requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructible< + decltype(std::get<0>(std::declval<_PairLike &&>())), + decltype(std::get<1>(std::declval<_PairLike &&>()))>()) _LIBCPP_HIDE_FROM_ABI constexpr explicit( !is_convertible_v(std::declval<_PairLike&&>())), first_type> || !is_convertible_v(std::declval<_PairLike&&>())), second_type>) pair(_PairLike&& __p) : first(std::get<0>(std::forward<_PairLike>(__p))), second(std::get<1>(std::forward<_PairLike>(__p))) {} + +# if __has_builtin(__reference_constructs_from_temporary) + template <__pair_like_no_subrange _PairLike> + requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted< + decltype(std::get<0>(std::declval<_PairLike &&>())), + decltype(std::get<1>(std::declval<_PairLike &&>()))>()) + explicit(!is_convertible_v(std::declval<_PairLike&&>())), first_type> || + !is_convertible_v(std::declval<_PairLike&&>())), second_type>) + pair(_PairLike&&) = delete; +# endif # endif template diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.observers/comp.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.observers/comp.pass.cpp index 5712493740bc8..626f6ad64c635 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.observers/comp.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.observers/comp.pass.cpp @@ -35,7 +35,7 @@ constexpr bool test() { assert(kc(1, 2)); assert(!kc(2, 1)); auto vc = m.value_comp(); - ASSERT_SAME_TYPE(decltype(vc(std::make_pair(1, 2), std::make_pair(1, 2))), bool); + ASSERT_SAME_TYPE(decltype(vc(std::make_pair(1, '2'), std::make_pair(1, '2'))), bool); assert(vc({1, '2'}, {2, '1'})); assert(!vc({2, '1'}, {1, '2'})); } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.observers/comp.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.observers/comp.pass.cpp index 070fbb0244e63..2b52b4722f347 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.observers/comp.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.observers/comp.pass.cpp @@ -36,7 +36,7 @@ constexpr bool test() { assert(kc(1, 2)); assert(!kc(2, 1)); auto vc = m.value_comp(); - ASSERT_SAME_TYPE(decltype(vc(std::make_pair(1, 2), std::make_pair(1, 2))), bool); + ASSERT_SAME_TYPE(decltype(vc(std::make_pair(1, '2'), std::make_pair(1, '2'))), bool); assert(vc({1, '2'}, {2, '1'})); assert(!vc({2, '1'}, {1, '2'})); } diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.U_V.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.U_V.pass.cpp index 33b5711e22183..63b254d102041 100644 --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.U_V.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.U_V.pass.cpp @@ -139,5 +139,15 @@ int main(int, char**) } #endif // TEST_STD_VER > 20 - return 0; +// Test construction prohibition of introduced by https://wg21.link/P2255R2. +#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + test_sfinae(); + test_sfinae(); + test_sfinae(); + test_sfinae(); + test_sfinae(); + test_sfinae(); +#endif // TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + + return 0; } diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.deleted.verify.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.deleted.verify.cpp new file mode 100644 index 0000000000000..12e2c5674bc56 --- /dev/null +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.deleted.verify.cpp @@ -0,0 +1,229 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++11 + +// + +// template struct pair + +// template +// constexpr explicit(see below) pair(U1&& x, U2&& y); // since C++11 + +// The constructor is defined as deleted if +// reference_constructs_from_temporary_v || reference_constructs_from_temporary_v +// is true. (since C++23) + +// template +// constexpr explicit(see below) pair(pair& p); // since C++23 +// template +// constexpr explicit(see below) pair(const pair& p); // since C++11 +// template +// constexpr explicit(see below) pair(pair&& p); // since C++11 +// template +// constexpr explicit(see below) pair(const pair&& p); // since C++23 +// template +// constexpr explicit(see below) pair(P&& p); // since C++23 + +// The constructor is defined as deleted if +// reference_constructs_from_temporary_v(FWD(p)))> || +// reference_constructs_from_temporary_v(FWD(p)))> +// is true. (since C++23) + +// Such reference binding used to cause hard error for these constructors before C++23 due to CWG1696. + +#include +#include +#include +#include + +#include "test_macros.h" + +void verify_two_arguments() { + std::pair p1{'a', 'b'}; +#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{call to deleted constructor of 'std::pair'}} +#else + // expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + // expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +#endif + +#if TEST_STD_VER >= 23 + std::pair p2({42L}, 'c'); +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{call to deleted constructor of 'std::pair'}} +# else + // expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif + + std::pair p3{'d', {}}; +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{call to deleted constructor of 'std::pair'}} +# else + // expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif +#endif +} + +void verify_pair_const_lvalue() { + const std::pair src1{'a', 'b'}; + std::pair dst1 = src1; + (void)dst1; +#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + // expected-error@-3 {{invokes a deleted function}} +#else + // expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +#endif + + const std::pair src2{'a', 'b'}; + std::pair dst2 = src2; + (void)dst2; +#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + // expected-error@-3 {{conversion function from 'const pair' to 'pair' invokes a deleted function}} +#else + // expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +#endif +} + +void verify_pair_rvalue() { + std::pair src1{'a', 'b'}; + std::pair dst1 = std::move(src1); + (void)dst1; +#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + // expected-error@-3 {{invokes a deleted function}} +#else + // expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +#endif + + std::pair src2{'a', 'b'}; + std::pair dst2 = std::move(src2); + (void)dst2; +#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + // expected-error@-3 {{invokes a deleted function}} +#else + // expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +#endif +} + +#if TEST_STD_VER >= 23 +void verify_pair_lvalue() { + std::pair src1{'a', 'b'}; + std::pair dst1 = src1; +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{invokes a deleted function}} +# else + // expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif + + std::pair src2{'a', 'b'}; + std::pair dst2 = src2; +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{invokes a deleted function}} +# else + // expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif +} + +void verify_pair_const_rvalue() { + const std::pair src1{'a', 'b'}; + std::pair dst1 = std::move(src1); +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{invokes a deleted function}} +# else + // expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif + + const std::pair src2{'a', 'b'}; + std::pair dst2 = std::move(src2); +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{invokes a deleted function}} +# else + // expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif +} + +void verify_pair_like() { + std::pair p1 = std::make_tuple('a', int{'b'}); +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{invokes a deleted function}} +# else + // expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif + + std::pair p2 = std::make_tuple(long{'a'}, 'b'); +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{invokes a deleted function}} +# else + // expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif + + std::pair p3 = std::array{'a', 'b'}; +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{invokes a deleted function}} +# else + // expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif + + std::pair p4 = std::array{'a', 'b'}; +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{invokes a deleted function}} +# else + // expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif + +# if TEST_STD_VER >= 26 + std::pair p5 = std::complex{42.0f, 1729.0f}; +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{invokes a deleted function}} +# else + // expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif + + std::pair p6 = std::complex{3.14159f, 2.71828f}; +# if __has_builtin(__reference_constructs_from_temporary) + // expected-error@-2 {{invokes a deleted function}} +# else + // expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} +# endif +# endif +} +#endif + +// Verify that copy-non-list-initialization ignores explicit but deleted overloads. +void verify_explicity() { + struct ExplicitlyToInt { + explicit operator int() const; + }; + + const std::pair src1; + std::pair dst1 = src1; // expected-error {{no viable conversion}} + + std::pair src2; + std::pair dst2 = std::move(src2); // expected-error {{no viable conversion}} + +#if TEST_STD_VER >= 23 + const std::pair src3; + std::pair dst3 = std::move(src3); // expected-error {{no viable conversion}} + + std::pair src4; + std::pair dst4 = src4; // expected-error {{no viable conversion}} + + std::pair dst5 = std::make_tuple(0, ExplicitlyToInt{}); // expected-error {{no viable conversion}} + + std::pair dst6 = std::array{}; // expected-error {{no viable conversion}} +#endif + +#if TEST_STD_VER >= 26 + struct ExplicitlyFromFloat { + explicit ExplicitlyFromFloat(float); + }; + + std::pair dst7 = // expected-error {{no viable conversion}} + std::complex{}; +#endif +} diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_move.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_move.pass.cpp index 63f409b332878..89eb6ab9dcea2 100644 --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_move.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_move.pass.cpp @@ -47,6 +47,14 @@ static_assert(!std::is_convertible_v&&, std::pair, ExplicitConstructibleFrom>>); // clang-format on +// Test construction prohibition of introduced by https://wg21.link/P2255R2. +#if __has_builtin(__reference_constructs_from_temporary) +static_assert(!std::is_constructible_v, const std::pair&&>); +static_assert(!std::is_constructible_v, const std::pair&&>); +static_assert(!std::is_convertible_v&&, std::pair>); +static_assert(!std::is_convertible_v&&, std::pair>); +#endif // __has_builtin(__reference_constructs_from_temporary) + constexpr bool test() { // simple case: init pair from const pair&& { diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_ref.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_ref.pass.cpp index 3a1e9ad08fb14..25ccc14428474 100644 --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_ref.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_ref.pass.cpp @@ -189,7 +189,18 @@ TEST_CONSTEXPR_CXX20 bool test() { static_assert(p2.second.value == 101, ""); } #endif - return true; + +// Test construction prohibition of introduced by https://wg21.link/P2255R2. +#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); +#endif // TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + + return true; } int main(int, char**) { diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp index 8ba9b5696eff1..ad144b0b8cac7 100644 --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp @@ -244,5 +244,15 @@ int main(int, char**) } #endif +// Test construction prohibition of introduced by https://wg21.link/P2255R2. +#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + test_pair_rv(); + test_pair_rv(); + test_pair_rv(); + test_pair_rv(); + test_pair_rv(); + test_pair_rv(); +#endif // TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + return 0; } diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_ref.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_ref.pass.cpp index 7ac70bf36a780..42d338b756917 100644 --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_ref.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_ref.pass.cpp @@ -42,6 +42,14 @@ static_assert(!std::is_convertible_v&, std::pair&, std::pair, ExplicitConstructibleFrom>>); // clang-format on +// Test construction prohibition of introduced by https://wg21.link/P2255R2. +#if __has_builtin(__reference_constructs_from_temporary) +static_assert(!std::is_constructible_v, std::pair&>); +static_assert(!std::is_constructible_v, std::pair&>); +static_assert(!std::is_convertible_v&, std::pair>); +static_assert(!std::is_convertible_v&, std::pair>); +#endif // __has_builtin(__reference_constructs_from_temporary) + constexpr bool test() { // use case in zip. Init pair from pair& { diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_like.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_like.pass.cpp index 135045d831d90..1ddfa5d03c810 100644 --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_like.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_like.pass.cpp @@ -17,12 +17,15 @@ #include #include +#include #include #include #include #include #include +#include "test_macros.h" + namespace my_ns{ struct MyPairLike { @@ -138,6 +141,49 @@ constexpr bool test() { static_assert(!std::is_convertible_v, std::pair>); } } + + // Test construction prohibition of introduced by https://wg21.link/P2255R2. +#if __has_builtin(__reference_constructs_from_temporary) + // Test tuple. + { + static_assert(!std::is_constructible_v, std::tuple>); + static_assert(!std::is_constructible_v, const std::tuple&>); + static_assert(!std::is_convertible_v, std::pair>); + static_assert(!std::is_convertible_v&, std::pair>); + + static_assert(!std::is_constructible_v, std::tuple>); + static_assert(!std::is_constructible_v, const std::tuple&>); + static_assert(!std::is_convertible_v, std::pair>); + static_assert(!std::is_convertible_v&, std::pair>); + } + // Test array. + { + static_assert(!std::is_constructible_v, std::array>); + static_assert(!std::is_constructible_v, std::array>); + static_assert(!std::is_constructible_v, const std::array&>); + static_assert(!std::is_constructible_v, const std::array&>); + + static_assert(!std::is_convertible_v, std::pair>); + static_assert(!std::is_convertible_v, std::pair>); + static_assert(!std::is_convertible_v&, std::pair>); + static_assert(!std::is_convertible_v&, std::pair>); + } +# if TEST_STD_VER >= 26 + // Test complex. + { + static_assert(!std::is_constructible_v, std::complex>); + static_assert(!std::is_constructible_v, std::complex>); + static_assert(!std::is_convertible_v, std::pair>); + static_assert(!std::is_convertible_v, std::pair>); + + static_assert(!std::is_constructible_v, const std::complex&>); + static_assert(!std::is_constructible_v, const std::complex&>); + static_assert(!std::is_convertible_v&, std::pair>); + static_assert(!std::is_convertible_v&, std::pair>); + } +# endif // TEST_STD_VER >= 26 +#endif // __has_builtin(__reference_constructs_from_temporary) + return true; }