[libcxx-commits] [libcxx] [libc++] P2255R2: Add deleted tuple constructor overloads (PR #205379)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jun 23 09:53:54 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Yihan Wang (yronglin)
<details>
<summary>Changes</summary>
Implements parts for `std::tuple` from P2255R2 "A type trait to detect reference binding to temporary".
Fixes https://github.com/llvm/llvm-project/issues/130403.
---
Patch is 29.55 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/205379.diff
4 Files Affected:
- (modified) libcxx/docs/Status/Cxx23Papers.csv (+1-1)
- (modified) libcxx/include/tuple (+223-24)
- (modified) libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.verify.cpp (+11-13)
- (added) libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/ref_constructs_from_temporary.verify.cpp (+74)
``````````diff
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index eb580ea891f5b..7e9f16fbe77ba 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 tuple constructors 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)","|Complete|","23","`#105184 <https://github.com/llvm/llvm-project/issues/105184>`__",""
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 2b32df6bce74a..fabf0a1a43a70 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -633,21 +633,55 @@ public:
_Not<_IsThisTuple<_Up...> >, // extension to allow mis-behaved user constructors
is_constructible<_Tp, _Up>... > {};
- template <class... _Up,
- __enable_if_t< _And< _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, _EnableUTypesCtor<_Up...> >::value,
- int> = 0>
+ template <class... _Up>
+ struct _EnableUTypesCtorBase
+ : _And<_BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, _EnableUTypesCtor<_Up...> > {};
+
+ template <bool, class... _Up>
+ struct _EnableUTypesCtorNoDangling : false_type {};
+
+# if _LIBCPP_STD_VER >= 23
+ template <bool, class... _Up>
+ struct _CtorCreatesDanglingReference : false_type {};
+
+ template <class... _Up>
+ struct _CtorCreatesDanglingReference<true, _Up...>
+ : _Or<_BoolConstant<__reference_constructs_from_temporary_v<_Tp, _Up&&> >...> {};
+
+ template <class... _Up>
+ struct _EnableUTypesCtorNoDangling<true, _Up...> : _Not<_CtorCreatesDanglingReference<true, _Up...> > {};
+
+ template <class... _Up>
+ struct _EnableDanglingUTypesCtor : _CtorCreatesDanglingReference<_EnableUTypesCtorBase<_Up...>::value, _Up...> {};
+# else
+ template <class... _Up>
+ struct _EnableUTypesCtorNoDangling<true, _Up...> : true_type {};
+# endif // _LIBCPP_STD_VER >= 23
+
+ template <class... _Up>
+ struct _EnableNonDanglingUTypesCtor
+ : _EnableUTypesCtorNoDangling<_EnableUTypesCtorBase<_Up...>::value, _Up...> {};
+
+ template <class... _Up, __enable_if_t< _EnableNonDanglingUTypesCtor<_Up...>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
tuple(_Up&&... __u) noexcept(_And<is_nothrow_constructible<_Tp, _Up>...>::value)
: __base_(__forward_args{}, std::forward<_Up>(__u)...) {}
- template <class _Alloc,
- class... _Up,
- __enable_if_t< _And< _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, _EnableUTypesCtor<_Up...> >::value,
- int> = 0>
+ template <class _Alloc, class... _Up, __enable_if_t< _EnableNonDanglingUTypesCtor<_Up...>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u)
: __base_(allocator_arg_t(), __a, __forward_args{}, std::forward<_Up>(__u)...) {}
+# if _LIBCPP_STD_VER >= 23
+ template <class... _Up, __enable_if_t< _EnableDanglingUTypesCtor<_Up...>::value, long> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
+ tuple(_Up&&...) noexcept(_And<is_nothrow_constructible<_Tp, _Up>...>::value) = delete;
+
+ template <class _Alloc, class... _Up, __enable_if_t< _EnableDanglingUTypesCtor<_Up...>::value, long> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
+ tuple(allocator_arg_t, const _Alloc&, _Up&&...) = delete;
+# endif // _LIBCPP_STD_VER >= 23
+
// Copy and move constructors (including the allocator_arg_t variants)
tuple(const tuple&) = default;
tuple(tuple&&) = default;
@@ -689,58 +723,134 @@ public:
_Not<is_convertible<_OtherTuple, _Tp> >...,
_Not<is_constructible<_Tp, _OtherTuple> >... > > > {};
- template <class... _Up, __enable_if_t< _And< _EnableCtorFromUTypesTuple<const tuple<_Up...>&> >::value, int> = 0>
+ template <bool, class _OtherTuple>
+ struct _EnableCtorFromUTypesTupleNoDangling : false_type {};
+
+# if _LIBCPP_STD_VER >= 23
+ template <bool, class _OtherTuple, class _DecayedOtherTuple = __remove_cvref_t<_OtherTuple>, class = void>
+ struct _CtorFromUTypesTupleCreatesDanglingReference : false_type {};
+
+ template <class _OtherTuple, class... _Up>
+ struct _CtorFromUTypesTupleCreatesDanglingReference<
+ true,
+ _OtherTuple,
+ tuple<_Up...>,
+ __enable_if_t<sizeof...(_Up) == sizeof...(_Tp)> >
+ : _Or<_BoolConstant<__reference_constructs_from_temporary_v<_Tp, __copy_cvref_t<_OtherTuple, _Up> > >...> {};
+
+ template <class _OtherTuple>
+ struct _EnableCtorFromUTypesTupleNoDangling<true, _OtherTuple>
+ : _Not<_CtorFromUTypesTupleCreatesDanglingReference<true, _OtherTuple> > {};
+
+ template <class _OtherTuple>
+ struct _EnableDanglingCtorFromUTypesTuple
+ : _CtorFromUTypesTupleCreatesDanglingReference<_EnableCtorFromUTypesTuple<_OtherTuple>::value, _OtherTuple> {};
+# else
+ template <class _OtherTuple>
+ struct _EnableCtorFromUTypesTupleNoDangling<true, _OtherTuple> : true_type {};
+# endif // _LIBCPP_STD_VER >= 23
+
+ template <class _OtherTuple>
+ struct _EnableNonDanglingCtorFromUTypesTuple
+ : _EnableCtorFromUTypesTupleNoDangling<_EnableCtorFromUTypesTuple<_OtherTuple>::value, _OtherTuple> {};
+
+ template <class... _Up,
+ __enable_if_t< _EnableNonDanglingCtorFromUTypesTuple<const tuple<_Up...>&>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_And<is_convertible<const _Up&, _Tp>...>::value)
tuple(const tuple<_Up...>& __t) noexcept(_And<is_nothrow_constructible<_Tp, const _Up&>...>::value)
: __base_(__from_tuple(), __t) {}
template <class... _Up,
class _Alloc,
- __enable_if_t< _And< _EnableCtorFromUTypesTuple<const tuple<_Up...>&> >::value, int> = 0>
+ __enable_if_t< _EnableNonDanglingCtorFromUTypesTuple<const tuple<_Up...>&>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!_And<is_convertible<const _Up&, _Tp>...>::value)
tuple(allocator_arg_t, const _Alloc& __a, const tuple<_Up...>& __t)
: __base_(allocator_arg_t(), __a, __from_tuple(), __t) {}
# if _LIBCPP_STD_VER >= 23
+ template <class... _Up,
+ __enable_if_t< _EnableDanglingCtorFromUTypesTuple<const tuple<_Up...>&>::value, long> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_And<is_convertible<const _Up&, _Tp>...>::value)
+ tuple(const tuple<_Up...>&) noexcept(_And<is_nothrow_constructible<_Tp, const _Up&>...>::value) = delete;
+
+ template <class... _Up,
+ class _Alloc,
+ __enable_if_t< _EnableDanglingCtorFromUTypesTuple<const tuple<_Up...>&>::value, long> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!_And<is_convertible<const _Up&, _Tp>...>::value)
+ tuple(allocator_arg_t, const _Alloc&, const tuple<_Up...>&) = delete;
+
// tuple(tuple<U...>&) constructors (including allocator_arg_t variants)
- template <class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
+ template <class... _Up, enable_if_t< _EnableNonDanglingCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<_Up&, _Tp>...>::value) tuple(tuple<_Up...>& __t)
: __base_(__from_tuple(), __t) {}
- template <class _Alloc, class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
+ template <class... _Up, enable_if_t< _EnableDanglingCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<_Up&, _Tp>...>::value) tuple(tuple<_Up...>&) = delete;
+
+ template <class _Alloc,
+ class... _Up,
+ enable_if_t< _EnableNonDanglingCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<_Up&, _Tp>...>::value)
tuple(allocator_arg_t, const _Alloc& __alloc, tuple<_Up...>& __t)
: __base_(allocator_arg_t(), __alloc, __from_tuple(), __t) {}
+
+ template <class _Alloc,
+ class... _Up,
+ enable_if_t< _EnableDanglingCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<_Up&, _Tp>...>::value)
+ tuple(allocator_arg_t, const _Alloc&, tuple<_Up...>&) = delete;
# endif // _LIBCPP_STD_VER >= 23
// tuple(tuple<U...>&&) constructors (including allocator_arg_t variants)
- template <class... _Up, __enable_if_t< _And< _EnableCtorFromUTypesTuple<tuple<_Up...>&&> >::value, int> = 0>
+ template <class... _Up,
+ __enable_if_t< _EnableNonDanglingCtorFromUTypesTuple<tuple<_Up...>&&>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
tuple(tuple<_Up...>&& __t) noexcept(_And<is_nothrow_constructible<_Tp, _Up>...>::value)
: __base_(__from_tuple(), std::move(__t)) {}
template <class _Alloc,
class... _Up,
- __enable_if_t< _And< _EnableCtorFromUTypesTuple<tuple<_Up...>&&> >::value, int> = 0>
+ __enable_if_t< _EnableNonDanglingCtorFromUTypesTuple<tuple<_Up...>&&>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
tuple(allocator_arg_t, const _Alloc& __a, tuple<_Up...>&& __t)
: __base_(allocator_arg_t(), __a, __from_tuple(), std::move(__t)) {}
# if _LIBCPP_STD_VER >= 23
+ template <class... _Up, __enable_if_t< _EnableDanglingCtorFromUTypesTuple<tuple<_Up...>&&>::value, long> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
+ tuple(tuple<_Up...>&&) noexcept(_And<is_nothrow_constructible<_Tp, _Up>...>::value) = delete;
+
+ template <class _Alloc,
+ class... _Up,
+ __enable_if_t< _EnableDanglingCtorFromUTypesTuple<tuple<_Up...>&&>::value, long> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
+ tuple(allocator_arg_t, const _Alloc&, tuple<_Up...>&&) = delete;
+
// tuple(const tuple<U...>&&) constructors (including allocator_arg_t variants)
- template <class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
+ template <class... _Up,
+ enable_if_t< _EnableNonDanglingCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<const _Up&&, _Tp>...>::value)
tuple(const tuple<_Up...>&& __t)
: __base_(__from_tuple(), std::move(__t)) {}
+ template <class... _Up, enable_if_t< _EnableDanglingCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<const _Up&&, _Tp>...>::value)
+ tuple(const tuple<_Up...>&&) = delete;
+
template <class _Alloc,
class... _Up,
- enable_if_t< _EnableCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
+ enable_if_t< _EnableNonDanglingCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<const _Up&&, _Tp>...>::value)
tuple(allocator_arg_t, const _Alloc& __alloc, const tuple<_Up...>&& __t)
: __base_(allocator_arg_t(), __alloc, __from_tuple(), std::move(__t)) {}
+
+ template <class _Alloc,
+ class... _Up,
+ enable_if_t< _EnableDanglingCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<const _Up&&, _Tp>...>::value)
+ tuple(allocator_arg_t, const _Alloc&, const tuple<_Up...>&&) = delete;
# endif // _LIBCPP_STD_VER >= 23
// tuple(const pair<U1, U2>&) constructors (including allocator_arg_t variants)
@@ -758,6 +868,34 @@ public:
template <class _Pair>
struct _EnableCtorFromPair : _CtorPredicateFromPair<is_constructible, _Pair> {};
+ template <bool, class _Pair>
+ struct _EnableCtorFromPairNoDangling : false_type {};
+
+# if _LIBCPP_STD_VER >= 23
+ template <bool, class _Pair, class _DecayedPair = __remove_cvref_t<_Pair>, class _Tuple = tuple>
+ struct _CtorFromPairCreatesDanglingReference : false_type {};
+
+ template <class _Pair, class _Up1, class _Up2, class _Tp1, class _Tp2>
+ struct _CtorFromPairCreatesDanglingReference<true, _Pair, pair<_Up1, _Up2>, tuple<_Tp1, _Tp2> >
+ : _Or<
+ _BoolConstant<__reference_constructs_from_temporary_v<_Tp1, __copy_cvref_t<_Pair, _Up1> > >,
+ _BoolConstant<__reference_constructs_from_temporary_v<_Tp2, __copy_cvref_t<_Pair, _Up2> > > > {};
+
+ template <class _Pair>
+ struct _EnableCtorFromPairNoDangling<true, _Pair> : _Not<_CtorFromPairCreatesDanglingReference<true, _Pair> > {};
+
+ template <class _Pair>
+ struct _EnableDanglingCtorFromPair
+ : _CtorFromPairCreatesDanglingReference<_EnableCtorFromPair<_Pair>::value, _Pair> {};
+# else
+ template <class _Pair>
+ struct _EnableCtorFromPairNoDangling<true, _Pair> : true_type {};
+# endif // _LIBCPP_STD_VER >= 23
+
+ template <class _Pair>
+ struct _EnableNonDanglingCtorFromPair
+ : _EnableCtorFromPairNoDangling<_EnableCtorFromPair<_Pair>::value, _Pair> {};
+
template <class _Pair>
struct _NothrowConstructibleFromPair : _CtorPredicateFromPair<is_nothrow_constructible, _Pair> {};
@@ -771,7 +909,7 @@ public:
template <class _Up1,
class _Up2,
template <class...> class _And = _And,
- __enable_if_t< _And< _EnableCtorFromPair<const pair<_Up1, _Up2>&> >::value, int> = 0>
+ __enable_if_t< _And< _EnableNonDanglingCtorFromPair<const pair<_Up1, _Up2>&> >::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_BothImplicitlyConvertible<const pair<_Up1, _Up2>&> >::value)
tuple(const pair<_Up1, _Up2>& __p) noexcept(_NothrowConstructibleFromPair<const pair<_Up1, _Up2>&>::value)
@@ -781,35 +919,64 @@ public:
class _Up1,
class _Up2,
template <class...> class _And = _And,
- __enable_if_t< _And< _EnableCtorFromPair<const pair<_Up1, _Up2>&> >::value, int> = 0>
+ __enable_if_t< _And< _EnableNonDanglingCtorFromPair<const pair<_Up1, _Up2>&> >::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_BothImplicitlyConvertible<const pair<_Up1, _Up2>&> >::value)
tuple(allocator_arg_t, const _Alloc& __a, const pair<_Up1, _Up2>& __p)
: __base_(allocator_arg_t(), __a, __from_tuple(), __p) {}
# if _LIBCPP_STD_VER >= 23
+ template <class _Up1,
+ class _Up2,
+ template <class...> class _And = _And,
+ __enable_if_t< _And< _EnableDanglingCtorFromPair<const pair<_Up1, _Up2>&> >::value, long> = 0>
+ _LIBCPP_HIDE_FROM_ABI
+ _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_BothImplicitlyConvertible<const pair<_Up1, _Up2>&> >::value)
+ tuple(const pair<_Up1, _Up2>&) noexcept(_NothrowConstructibleFromPair<const pair<_Up1, _Up2>&>::value) =
+ delete;
+
+ template <class _Alloc,
+ class _Up1,
+ class _Up2,
+ template <class...> class _And = _And,
+ __enable_if_t< _And< _EnableDanglingCtorFromPair<const pair<_Up1, _Up2>&> >::value, long> = 0>
+ _LIBCPP_HIDE_FROM_ABI
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_BothImplicitlyConvertible<const pair<_Up1, _Up2>&> >::value)
+ tuple(allocator_arg_t, const _Alloc&, const pair<_Up1, _Up2>&) = delete;
+
// tuple(pair<U1, U2>&) constructors (including allocator_arg_t variants)
- template <class _U1, class _U2, enable_if_t< _EnableCtorFromPair<pair<_U1, _U2>&>::value>* = nullptr>
+ template <class _U1, class _U2, enable_if_t< _EnableNonDanglingCtorFromPair<pair<_U1, _U2>&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_BothImplicitlyConvertible<pair<_U1, _U2>&>::value)
tuple(pair<_U1, _U2>& __p)
: __base_(__from_tuple(), __p) {}
+ template <class _U1, class _U2, enable_if_t< _EnableDanglingCtorFromPair<pair<_U1, _U2>&>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_BothImplicitlyConvertible<pair<_U1, _U2>&>::value)
+ tuple(pair<_U1, _U2>&) = delete;
+
template <class _Alloc,
class _U1,
class _U2,
- enable_if_t< _EnableCtorFromPair<std::pair<_U1, _U2>&>::value>* = nullptr>
+ enable_if_t< _EnableNonDanglingCtorFromPair<std::pair<_U1, _U2>&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_BothImplicitlyConvertible<pair<_U1, _U2>&>::value)
tuple(allocator_arg_t, const _Alloc& __alloc, pair<_U1, _U2>& __p)
: __base_(allocator_arg_t(), __alloc, __from_tuple(), __p) {}
-# endif
+
+ template <class _Alloc,
+ class _U1,
+ class _U2,
+ enable_if_t< _EnableDanglingCtorFromPair<std::pair<_U1, _U2>&>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_BothImplicitlyConvertible<pair<_U1, _U2>&>::value)
+ tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete;
+# endif // _LIBCPP_STD_VER >= 23
// tuple(pair<U1, U2>&&) constructors (including allocator_arg_t variants)
template <class _Up1,
class _Up2,
template <class...> class _And = _And,
- __enable_if_t< _And< _EnableCtorFromPair<pair<_Up1, _Up2>&&> >::value, int> = 0>
+ __enable_if_t< _And< _EnableNonDanglingCtorFromPair<pair<_Up1, _Up2>&&> >::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_BothImplicitlyConvertible<pair<_Up1, _Up2>&&> >::value)
tuple(pair<_Up1, _Up2>&& __p) noexcept(_NothrowConstructibleFromPair<pair<_Up1, _Up2>&&>::value)
@@ -819,27 +986,59 @@ public:
class _Up1,
class _Up2,
template <class...> class _And = _And,
- __enable_if_t< _And< _EnableCtorFromPair<pair<_Up1, _Up2>&&> >::value, int> = 0>
+ __enable_if_t< _And< _EnableNonDanglingCtorFromPair<pair<_Up1, _Up2>&&> >::value, int> = 0>
...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/205379
More information about the libcxx-commits
mailing list