[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