[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