[libcxx-commits] [libcxx] [libc++] P2255R2: Add deleted tuple constructor overloads (PR #205379)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jun 23 10:11:24 PDT 2026


================
@@ -689,58 +721,129 @@ 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;
----------------
frederick-vs-ja wrote:

I believe for deleted overloads, `_LIBCPP_HIDE_FROM_ABI`, `constexpr`, and `noexcept` don't make sense, and we can drop them for clarity. Although we should keep `explicit` as it affects overload resolution.
```suggestion
  explicit(!_And<is_convertible<const _Up&, _Tp>...>::value) tuple(const tuple<_Up...>&) = delete;
```
(ditto below)

https://github.com/llvm/llvm-project/pull/205379


More information about the libcxx-commits mailing list