[libcxx-commits] [libcxx] [libc++] P2255R2: Add deleted `pair` constructor overloads (PR #164214)
via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Oct 20 00:59:31 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: A. Jiang (frederick-vs-ja)
<details>
<summary>Changes</summary>
Implements parts for `std::pair` from P2255R2 "A type trait to detect reference binding to temporary".
Fixes #<!-- -->129051.
---
Patch is 31.53 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/164214.diff
11 Files Affected:
- (modified) libcxx/docs/Status/Cxx23Papers.csv (+1-1)
- (modified) libcxx/include/__utility/pair.h (+68-8)
- (modified) libcxx/test/std/containers/container.adaptors/flat.map/flat.map.observers/comp.pass.cpp (+1-1)
- (modified) libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.observers/comp.pass.cpp (+1-1)
- (modified) libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.U_V.pass.cpp (+11-1)
- (added) libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.deleted.verify.cpp (+225)
- (modified) libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_move.pass.cpp (+8)
- (modified) libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_ref.pass.cpp (+12-1)
- (modified) libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp (+10)
- (modified) libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_ref.pass.cpp (+8)
- (modified) libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_like.pass.cpp (+46)
``````````diff
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 <https://wg21.link/P0627R6>`__","Function to mark unreachable code","2022-02 (Virtual)","|Complete|","15","`#105175 <https://github.com/llvm/llvm-project/issues/105175>`__",""
"`P1206R7 <https://wg21.link/P1206R7>`__","``ranges::to``: A function to convert any range to a container","2022-02 (Virtual)","|Complete|","17","`#105176 <https://github.com/llvm/llvm-project/issues/105176>`__",""
"`P1413R3 <https://wg21.link/P1413R3>`__","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","2022-02 (Virtual)","|Complete|","","`#105177 <https://github.com/llvm/llvm-project/issues/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 <https://wg21.link/P2255R2>`__","A type trait to detect reference binding to temporary","2022-02 (Virtual)","|Partial|","","`#105180 <https://github.com/llvm/llvm-project/issues/105180>`__","Implemented the type traits only."
+"`P2255R2 <https://wg21.link/P2255R2>`__","A type trait to detect reference binding to temporary","2022-02 (Virtual)","|Partial|","","`#105180 <https://github.com/llvm/llvm-project/issues/105180>`__","Implemented the type traits and changes to ``std::pair`` only."
"`P2273R3 <https://wg21.link/P2273R3>`__","Making ``std::unique_ptr`` constexpr","2022-02 (Virtual)","|Complete|","16","`#105182 <https://github.com/llvm/llvm-project/issues/105182>`__",""
"`P2387R3 <https://wg21.link/P2387R3>`__","Pipe support for user-defined range adaptors","2022-02 (Virtual)","|Complete|","19","`#105183 <https://github.com/llvm/llvm-project/issues/105183>`__",""
"`P2440R1 <https://wg21.link/P2440R1>`__","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","2022-02 (Virtual)","|Partial|","","`#105184 <https://github.com/llvm/llvm-project/issues/105184>`__","Only ``ranges::iota`` is implemented."
diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h
index 33694c52430f1..7ab475a49ab38 100644
--- a/libcxx/include/__utility/pair.h
+++ b/libcxx/include/__utility/pair.h
@@ -36,6 +36,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 +69,23 @@ struct __check_pair_construction {
template <class _U1, class _U2>
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 <class _U1, class _U2>
+ 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 <class _U1, class _U2>
static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_implicit() {
return is_convertible<_U1, _T1>::value && is_convertible<_U2, _T2>::value;
@@ -157,14 +172,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<first_type, _U1>::value &&
is_nothrow_constructible<second_type, _U2>::value)
: first(std::forward<_U1>(__u1)), second(std::forward<_U2>(__u2)) {
}
+# if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)
+ template <class _U1 = _T1, class _U2 = _T2>
+ 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 <class _U1,
class _U2,
@@ -173,6 +194,12 @@ struct pair
pair(pair<_U1, _U2>& __p) noexcept((is_nothrow_constructible<first_type, _U1&>::value &&
is_nothrow_constructible<second_type, _U2&>::value))
: first(__p.first), second(__p.second) {}
+
+# if __has_builtin(__reference_constructs_from_temporary)
+ template <class _U1, class _U2>
+ 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 +213,30 @@ struct pair
is_nothrow_constructible<second_type, _U2 const&>::value)
: first(__p.first), second(__p.second) {}
- template <class _U1,
- class _U2,
- __enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1, _U2>(), int> = 0>
+# if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)
+ template <class _U1, class _U2>
+ requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted<const _U1&, const _U2&>())
+ explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<const _U1&, const _U2&>())
+ 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<first_type, _U1&&>::value &&
is_nothrow_constructible<second_type, _U2&&>::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 <class _U1, class _U2>
+ 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 +248,34 @@ struct pair
pair(const pair<_U1, _U2>&& __p) noexcept(is_nothrow_constructible<first_type, const _U1&&>::value &&
is_nothrow_constructible<second_type, const _U2&&>::value)
: first(std::move(__p.first)), second(std::move(__p.second)) {}
+
+# if __has_builtin(__reference_constructs_from_temporary)
+ template <class _U1, class _U2>
+ requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted<const _U1 &&, const _U2 &&>())
+ explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<const _U1&&, const _U2&&>())
+ pair(const pair<_U1, _U2>&&) = delete;
+# endif
# endif
# if _LIBCPP_STD_VER >= 23
template <__pair_like_no_subrange _PairLike>
- requires(is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> &&
- is_constructible_v<second_type, decltype(std::get<1>(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<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> ||
!is_convertible_v<decltype(std::get<1>(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<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> ||
+ !is_convertible_v<decltype(std::get<1>(std::declval<_PairLike&&>())), second_type>)
+ pair(_PairLike&&) = delete;
+# endif
# endif
template <class... _Args1, class... _Args2>
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<int&&, char, false>();
+ test_sfinae<const int&, char, false>();
+ test_sfinae<ConvertingType&&, int, false>();
+ test_sfinae<const ConvertingType&, char, false>();
+ test_sfinae<ExplicitTypes::ConvertingType&&, int, false>();
+ test_sfinae<const ExplicitTypes::ConvertingType&, int, false>();
+#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..0b1bfc097965b
--- /dev/null
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.deleted.verify.cpp
@@ -0,0 +1,225 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <utility>
+
+// template <class T1, class T2> struct pair
+
+// template<class U1 = T1, class U2 = T2>
+// constexpr explicit(see below) pair(U1&& x, U2&& y); // since C++11
+
+// The constructor is defined as deleted if
+// reference_constructs_from_temporary_v<first_type, U1&&> || reference_constructs_from_temporary_v<second_type, U2>
+// is true. (since C++23)
+
+// template<class U1, class U2>
+// constexpr explicit(see below) pair(pair<U1, U2>& p); // since C++23
+// template<class U1, class U2>
+// constexpr explicit(see below) pair(const pair<U1, U2>& p); // since C++11
+// template<class U1, class U2>
+// constexpr explicit(see below) pair(pair<U1, U2>&& p); // since C++11
+// template<class U1, class U2>
+// constexpr explicit(see below) pair(const pair<U1, U2>&& p); // since C++23
+// template<pair-like P>
+// constexpr explicit(see below) pair(P&& p); // since C++23
+
+// The constructor is defined as deleted if
+// reference_constructs_from_temporary_v<first_type, decltype(get<0>(FWD(p)))> ||
+// reference_constructs_from_temporary_v<second_type, decltype(get<1>(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 <array>
+#include <complex>
+#include <tuple>
+#include <utility>
+
+#include "test_macros.h"
+
+void verify_two_arguments() {
+ std::pair<const long&, int&&> p1{'a', 'b'};
+#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, int &&>'}}
+#else
+ // expected-error at -4 {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
+ // expected-error at -5 {{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<const long, int&&> p2({42L}, 'c');
+# if __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long, int &&>'}}
+# else
+ // expected-error at -4 {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
+# endif
+
+ std::pair<const long&, int> p3{'d', {}};
+# if __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, int>'}}
+# else
+ // expected-error at -4 {{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<char, int> src1{'a', 'b'};
+ std::pair<const long&, const int&> dst1 = src1;
+#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, const int &>'}}
+#else
+ // expected-error at -4 {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
+#endif
+
+ const std::pair<long, char> src2{'a', 'b'};
+ std::pair<const long&, const int&> dst2 = src2;
+#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, const int &>'}}
+#else
+ // expected-error at -4 {{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<char, int> src1{'a', 'b'};
+ std::pair<const long&, int&&> dst1 = std::move(src1);
+#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, int &&>'}}
+#else
+ // expected-error at -4 {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
+#endif
+
+ std::pair<long, char> src2{'a', 'b'};
+ std::pair<const long&, int&&> dst2 = std::move(src2);
+#if TEST_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, int &&>'}}
+#else
+ // expected-error at -4 {{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<char, int> src1{'a', 'b'};
+ std::pair<const long&, int&> dst1 = src1;
+# if __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, int &>'}}
+# else
+ // expected-error at -4 {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
+# endif
+
+ std::pair<long, char> src2{'a', 'b'};
+ std::pair<const long&, int&&> dst2 = src2;
+# if __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, int &&>'}}
+# else
+ // expected-error at -4 {{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<char, int> src1{'a', 'b'};
+ std::pair<const long&, const int&&> dst1 = std::move(src1);
+# if __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, const int &&>'}}
+# else
+ // expected-error at -4 {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
+# endif
+
+ const std::pair<long, char> src2{'a', 'b'};
+ std::pair<const long&, const int&&> dst2 = std::move(src2);
+# if __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, const int &&>'}}
+# else
+ // expected-error at -4 {{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<const long&, int&&> p1 = std::make_tuple('a', int{'b'});
+# if __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, const int &&>'}}
+# else
+ // expected-error at -4 {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
+# endif
+
+ std::pair<const long&, int&&> p2 = std::make_tuple(long{'a'}, 'b');
+# if __has_builtin(__reference_constructs_from_temporary)
+ // expected-error at -2 {{call to deleted constructor of 'std::pair<const long &, int &&>'}}
+# else
...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/164214
More information about the libcxx-commits
mailing list