[libcxx-commits] [libcxx] [libc++] Add tag types to all the __tuple_impl constructors (PR #154517)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Aug 20 06:38:52 PDT 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/154517
>From c269cdda89e73783fc702bbf91967ec1f00720a1 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 20 Aug 2025 13:35:30 +0200
Subject: [PATCH] [libc++] Add tag types to all the __tuple_impl constructors
---
libcxx/include/tuple | 40 ++++++++++---------
.../move_ctor_sfinae.compile.pass.cpp | 29 ++++++++++++++
2 files changed, 50 insertions(+), 19 deletions(-)
create mode 100644 libcxx/test/std/utilities/tuple/tuple.tuple/move_ctor_sfinae.compile.pass.cpp
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index b046e2aed43e2..bef718684023c 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -516,6 +516,7 @@ struct __tuple_impl;
struct __forward_args {};
struct __value_init {};
+struct __from_tuple {};
template <size_t... _Indx, class... _Tp>
struct _LIBCPP_DECLSPEC_EMPTY_BASES
@@ -538,7 +539,7 @@ struct _LIBCPP_DECLSPEC_EMPTY_BASES
: __tuple_leaf<_Indx, _Tp>(__uses_alloc_ctor<_Tp, _Alloc, _Args>(), __alloc, std::forward<_Args>(__args))... {}
template <class _Tuple>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_impl(_Tuple&& __t) noexcept(
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_impl(__from_tuple, _Tuple&& __t) noexcept(
(__all<is_nothrow_constructible<
_Tp,
typename tuple_element<_Indx, typename __make_tuple_types<_Tuple>::type>::type>::value...>::value))
@@ -547,7 +548,8 @@ struct _LIBCPP_DECLSPEC_EMPTY_BASES
std::get<_Indx>(__t)))... {}
template <class _Alloc, class _Tuple>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_impl(allocator_arg_t, const _Alloc& __a, _Tuple&& __t)
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
+ __tuple_impl(allocator_arg_t, const _Alloc& __a, __from_tuple, _Tuple&& __t)
: __tuple_leaf<_Indx, _Tp>(
__uses_alloc_ctor<_Tp,
_Alloc,
@@ -673,13 +675,13 @@ public:
template <class...> class _And = _And,
__enable_if_t< _And<is_copy_constructible<_Tp>...>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple(allocator_arg_t, const _Alloc& __alloc, const tuple& __t)
- : __base_(allocator_arg_t(), __alloc, __t) {}
+ : __base_(allocator_arg_t(), __alloc, __from_tuple(), __t) {}
template <class _Alloc,
template <class...> class _And = _And,
__enable_if_t< _And<is_move_constructible<_Tp>...>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple(allocator_arg_t, const _Alloc& __alloc, tuple&& __t)
- : __base_(allocator_arg_t(), __alloc, std::move(__t)) {}
+ : __base_(allocator_arg_t(), __alloc, __from_tuple(), std::move(__t)) {}
// tuple(const tuple<U...>&) constructors (including allocator_arg_t variants)
@@ -712,7 +714,7 @@ public:
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> >::value)
tuple(const tuple<_Up...>& __t) noexcept(_And<is_nothrow_constructible<_Tp, const _Up&>...>::value)
- : __base_(__t) {}
+ : __base_(__from_tuple(), __t) {}
template <class... _Up,
class _Alloc,
@@ -720,33 +722,33 @@ public:
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> >::value)
tuple(allocator_arg_t, const _Alloc& __a, const tuple<_Up...>& __t)
- : __base_(allocator_arg_t(), __a, __t) {}
+ : __base_(allocator_arg_t(), __a, __from_tuple(), __t) {}
# if _LIBCPP_STD_VER >= 23
// tuple(tuple<U...>&) constructors (including allocator_arg_t variants)
template <class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<_Up&, _Tp>...>::value) tuple(tuple<_Up...>& __t)
- : __base_(__t) {}
+ : __base_(__from_tuple(), __t) {}
template <class _Alloc, class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<_Up&, _Tp>...>::value)
tuple(allocator_arg_t, const _Alloc& __alloc, tuple<_Up...>& __t)
- : __base_(allocator_arg_t(), __alloc, __t) {}
+ : __base_(allocator_arg_t(), __alloc, __from_tuple(), __t) {}
# 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>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> >::value)
tuple(tuple<_Up...>&& __t) noexcept(_And<is_nothrow_constructible<_Tp, _Up>...>::value)
- : __base_(std::move(__t)) {}
+ : __base_(__from_tuple(), std::move(__t)) {}
template <class _Alloc,
class... _Up,
__enable_if_t< _And< _EnableCtorFromUTypesTuple<tuple<_Up...>&&> >::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> >::value)
tuple(allocator_arg_t, const _Alloc& __a, tuple<_Up...>&& __t)
- : __base_(allocator_arg_t(), __a, std::move(__t)) {}
+ : __base_(allocator_arg_t(), __a, __from_tuple(), std::move(__t)) {}
# if _LIBCPP_STD_VER >= 23
// tuple(const tuple<U...>&&) constructors (including allocator_arg_t variants)
@@ -754,14 +756,14 @@ public:
template <class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<const _Up&&, _Tp>...>::value)
tuple(const tuple<_Up...>&& __t)
- : __base_(std::move(__t)) {}
+ : __base_(__from_tuple(), std::move(__t)) {}
template <class _Alloc,
class... _Up,
enable_if_t< _EnableCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<const _Up&&, _Tp>...>::value)
tuple(allocator_arg_t, const _Alloc& __alloc, const tuple<_Up...>&& __t)
- : __base_(allocator_arg_t(), __alloc, std::move(__t)) {}
+ : __base_(allocator_arg_t(), __alloc, __from_tuple(), std::move(__t)) {}
# endif // _LIBCPP_STD_VER >= 23
// tuple(const pair<U1, U2>&) constructors (including allocator_arg_t variants)
@@ -796,7 +798,7 @@ public:
_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)
- : __base_(__p) {}
+ : __base_(__from_tuple(), __p) {}
template <class _Alloc,
class _Up1,
@@ -814,7 +816,7 @@ public:
template <class _U1, class _U2, enable_if_t< _EnableCtorFromPair<pair<_U1, _U2>&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_BothImplicitlyConvertible<pair<_U1, _U2>&>::value)
tuple(pair<_U1, _U2>& __p)
- : __base_(__p) {}
+ : __base_(__from_tuple(), __p) {}
template <class _Alloc,
class _U1,
@@ -822,7 +824,7 @@ public:
enable_if_t< _EnableCtorFromPair<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, __p) {}
+ : __base_(allocator_arg_t(), __alloc, __from_tuple(), __p) {}
# endif
// tuple(pair<U1, U2>&&) constructors (including allocator_arg_t variants)
@@ -834,7 +836,7 @@ public:
_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)
- : __base_(std::move(__p)) {}
+ : __base_(__from_tuple(), std::move(__p)) {}
template <class _Alloc,
class _Up1,
@@ -844,7 +846,7 @@ public:
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_BothImplicitlyConvertible<pair<_Up1, _Up2>&&> >::value)
tuple(allocator_arg_t, const _Alloc& __a, pair<_Up1, _Up2>&& __p)
- : __base_(allocator_arg_t(), __a, std::move(__p)) {}
+ : __base_(allocator_arg_t(), __a, __from_tuple(), std::move(__p)) {}
# if _LIBCPP_STD_VER >= 23
// tuple(const pair<U1, U2>&&) constructors (including allocator_arg_t variants)
@@ -852,7 +854,7 @@ public:
template <class _U1, class _U2, enable_if_t< _EnableCtorFromPair<const pair<_U1, _U2>&&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_BothImplicitlyConvertible<const pair<_U1, _U2>&&>::value)
tuple(const pair<_U1, _U2>&& __p)
- : __base_(std::move(__p)) {}
+ : __base_(__from_tuple(), std::move(__p)) {}
template <class _Alloc,
class _U1,
@@ -860,7 +862,7 @@ public:
enable_if_t< _EnableCtorFromPair<const pair<_U1, _U2>&&>::value>* = nullptr>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_BothImplicitlyConvertible<const pair<_U1, _U2>&&>::value)
tuple(allocator_arg_t, const _Alloc& __alloc, const pair<_U1, _U2>&& __p)
- : __base_(allocator_arg_t(), __alloc, std::move(__p)) {}
+ : __base_(allocator_arg_t(), __alloc, __from_tuple(), std::move(__p)) {}
# endif // _LIBCPP_STD_VER >= 23
// [tuple.assign]
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/move_ctor_sfinae.compile.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/move_ctor_sfinae.compile.pass.cpp
new file mode 100644
index 0000000000000..6eeaae9fb5c8f
--- /dev/null
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/move_ctor_sfinae.compile.pass.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Ensure that tuple's move constructor properly SFINAES.
+// This is a regression test for https://github.com/llvm/llvm-project/pull/151654#issuecomment-3205410955
+
+// UNSUPPORTED: c++03
+
+#include <tuple>
+#include <variant>
+#include <type_traits>
+
+struct S {
+ S(const S&) = delete;
+ S& operator=(const S&) = delete;
+ S(S&&) = default;
+ S& operator=(S&&) = default;
+};
+
+using T = std::tuple<const std::variant<S>>;
+
+void func() {
+ (void)std::is_trivially_move_constructible<T>::value;
+}
More information about the libcxx-commits
mailing list