Skip to content

Commit d9a192c

Browse files
authored
[libc++] Add tag types to all the __tuple_impl constructors (#154517)
This fixes a bug reported in #151654 (comment).
1 parent b12e47c commit d9a192c

File tree

2 files changed

+49
-20
lines changed

2 files changed

+49
-20
lines changed

libcxx/include/tuple

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ struct __tuple_impl;
516516

517517
struct __forward_args {};
518518
struct __value_init {};
519+
struct __from_tuple {};
519520

520521
template <size_t... _Indx, class... _Tp>
521522
struct _LIBCPP_DECLSPEC_EMPTY_BASES
@@ -538,7 +539,7 @@ struct _LIBCPP_DECLSPEC_EMPTY_BASES
538539
: __tuple_leaf<_Indx, _Tp>(__uses_alloc_ctor<_Tp, _Alloc, _Args>(), __alloc, std::forward<_Args>(__args))... {}
539540

540541
template <class _Tuple>
541-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_impl(_Tuple&& __t) noexcept(
542+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_impl(__from_tuple, _Tuple&& __t) noexcept(
542543
(__all<is_nothrow_constructible<
543544
_Tp,
544545
typename tuple_element<_Indx, typename __make_tuple_types<_Tuple>::type>::type>::value...>::value))
@@ -547,7 +548,8 @@ struct _LIBCPP_DECLSPEC_EMPTY_BASES
547548
std::get<_Indx>(__t)))... {}
548549

549550
template <class _Alloc, class _Tuple>
550-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_impl(allocator_arg_t, const _Alloc& __a, _Tuple&& __t)
551+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
552+
__tuple_impl(allocator_arg_t, const _Alloc& __a, __from_tuple, _Tuple&& __t)
551553
: __tuple_leaf<_Indx, _Tp>(
552554
__uses_alloc_ctor<_Tp,
553555
_Alloc,
@@ -673,13 +675,13 @@ public:
673675
template <class...> class _And = _And,
674676
__enable_if_t< _And<is_copy_constructible<_Tp>...>::value, int> = 0>
675677
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple(allocator_arg_t, const _Alloc& __alloc, const tuple& __t)
676-
: __base_(allocator_arg_t(), __alloc, __t) {}
678+
: __base_(allocator_arg_t(), __alloc, __from_tuple(), __t) {}
677679

678680
template <class _Alloc,
679681
template <class...> class _And = _And,
680682
__enable_if_t< _And<is_move_constructible<_Tp>...>::value, int> = 0>
681683
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple(allocator_arg_t, const _Alloc& __alloc, tuple&& __t)
682-
: __base_(allocator_arg_t(), __alloc, std::move(__t)) {}
684+
: __base_(allocator_arg_t(), __alloc, __from_tuple(), std::move(__t)) {}
683685

684686
// tuple(const tuple<U...>&) constructors (including allocator_arg_t variants)
685687

@@ -712,56 +714,56 @@ public:
712714
_LIBCPP_HIDE_FROM_ABI
713715
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> >::value)
714716
tuple(const tuple<_Up...>& __t) noexcept(_And<is_nothrow_constructible<_Tp, const _Up&>...>::value)
715-
: __base_(__t) {}
717+
: __base_(__from_tuple(), __t) {}
716718

717719
template <class... _Up,
718720
class _Alloc,
719721
__enable_if_t< _And< _EnableCtorFromUTypesTuple<const tuple<_Up...>&> >::value, int> = 0>
720722
_LIBCPP_HIDE_FROM_ABI
721723
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> >::value)
722724
tuple(allocator_arg_t, const _Alloc& __a, const tuple<_Up...>& __t)
723-
: __base_(allocator_arg_t(), __a, __t) {}
725+
: __base_(allocator_arg_t(), __a, __from_tuple(), __t) {}
724726

725727
# if _LIBCPP_STD_VER >= 23
726728
// tuple(tuple<U...>&) constructors (including allocator_arg_t variants)
727729

728730
template <class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
729731
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<_Up&, _Tp>...>::value) tuple(tuple<_Up...>& __t)
730-
: __base_(__t) {}
732+
: __base_(__from_tuple(), __t) {}
731733

732734
template <class _Alloc, class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
733735
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<_Up&, _Tp>...>::value)
734736
tuple(allocator_arg_t, const _Alloc& __alloc, tuple<_Up...>& __t)
735-
: __base_(allocator_arg_t(), __alloc, __t) {}
737+
: __base_(allocator_arg_t(), __alloc, __from_tuple(), __t) {}
736738
# endif // _LIBCPP_STD_VER >= 23
737739

738740
// tuple(tuple<U...>&&) constructors (including allocator_arg_t variants)
739741
template <class... _Up, __enable_if_t< _And< _EnableCtorFromUTypesTuple<tuple<_Up...>&&> >::value, int> = 0>
740742
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> >::value)
741743
tuple(tuple<_Up...>&& __t) noexcept(_And<is_nothrow_constructible<_Tp, _Up>...>::value)
742-
: __base_(std::move(__t)) {}
744+
: __base_(__from_tuple(), std::move(__t)) {}
743745

744746
template <class _Alloc,
745747
class... _Up,
746748
__enable_if_t< _And< _EnableCtorFromUTypesTuple<tuple<_Up...>&&> >::value, int> = 0>
747749
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> >::value)
748750
tuple(allocator_arg_t, const _Alloc& __a, tuple<_Up...>&& __t)
749-
: __base_(allocator_arg_t(), __a, std::move(__t)) {}
751+
: __base_(allocator_arg_t(), __a, __from_tuple(), std::move(__t)) {}
750752

751753
# if _LIBCPP_STD_VER >= 23
752754
// tuple(const tuple<U...>&&) constructors (including allocator_arg_t variants)
753755

754756
template <class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
755757
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<const _Up&&, _Tp>...>::value)
756758
tuple(const tuple<_Up...>&& __t)
757-
: __base_(std::move(__t)) {}
759+
: __base_(__from_tuple(), std::move(__t)) {}
758760

759761
template <class _Alloc,
760762
class... _Up,
761763
enable_if_t< _EnableCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
762764
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<const _Up&&, _Tp>...>::value)
763765
tuple(allocator_arg_t, const _Alloc& __alloc, const tuple<_Up...>&& __t)
764-
: __base_(allocator_arg_t(), __alloc, std::move(__t)) {}
766+
: __base_(allocator_arg_t(), __alloc, __from_tuple(), std::move(__t)) {}
765767
# endif // _LIBCPP_STD_VER >= 23
766768

767769
// tuple(const pair<U1, U2>&) constructors (including allocator_arg_t variants)
@@ -796,7 +798,7 @@ public:
796798
_LIBCPP_HIDE_FROM_ABI
797799
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_BothImplicitlyConvertible<const pair<_Up1, _Up2>&> >::value)
798800
tuple(const pair<_Up1, _Up2>& __p) noexcept(_NothrowConstructibleFromPair<const pair<_Up1, _Up2>&>::value)
799-
: __base_(__p) {}
801+
: __base_(__from_tuple(), __p) {}
800802

801803
template <class _Alloc,
802804
class _Up1,
@@ -806,23 +808,23 @@ public:
806808
_LIBCPP_HIDE_FROM_ABI
807809
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_BothImplicitlyConvertible<const pair<_Up1, _Up2>&> >::value)
808810
tuple(allocator_arg_t, const _Alloc& __a, const pair<_Up1, _Up2>& __p)
809-
: __base_(allocator_arg_t(), __a, __p) {}
811+
: __base_(allocator_arg_t(), __a, __from_tuple(), __p) {}
810812

811813
# if _LIBCPP_STD_VER >= 23
812814
// tuple(pair<U1, U2>&) constructors (including allocator_arg_t variants)
813815

814816
template <class _U1, class _U2, enable_if_t< _EnableCtorFromPair<pair<_U1, _U2>&>::value>* = nullptr>
815817
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_BothImplicitlyConvertible<pair<_U1, _U2>&>::value)
816818
tuple(pair<_U1, _U2>& __p)
817-
: __base_(__p) {}
819+
: __base_(__from_tuple(), __p) {}
818820

819821
template <class _Alloc,
820822
class _U1,
821823
class _U2,
822824
enable_if_t< _EnableCtorFromPair<std::pair<_U1, _U2>&>::value>* = nullptr>
823825
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_BothImplicitlyConvertible<pair<_U1, _U2>&>::value)
824826
tuple(allocator_arg_t, const _Alloc& __alloc, pair<_U1, _U2>& __p)
825-
: __base_(allocator_arg_t(), __alloc, __p) {}
827+
: __base_(allocator_arg_t(), __alloc, __from_tuple(), __p) {}
826828
# endif
827829

828830
// tuple(pair<U1, U2>&&) constructors (including allocator_arg_t variants)
@@ -834,7 +836,7 @@ public:
834836
_LIBCPP_HIDE_FROM_ABI
835837
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_BothImplicitlyConvertible<pair<_Up1, _Up2>&&> >::value)
836838
tuple(pair<_Up1, _Up2>&& __p) noexcept(_NothrowConstructibleFromPair<pair<_Up1, _Up2>&&>::value)
837-
: __base_(std::move(__p)) {}
839+
: __base_(__from_tuple(), std::move(__p)) {}
838840

839841
template <class _Alloc,
840842
class _Up1,
@@ -844,23 +846,23 @@ public:
844846
_LIBCPP_HIDE_FROM_ABI
845847
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_BothImplicitlyConvertible<pair<_Up1, _Up2>&&> >::value)
846848
tuple(allocator_arg_t, const _Alloc& __a, pair<_Up1, _Up2>&& __p)
847-
: __base_(allocator_arg_t(), __a, std::move(__p)) {}
849+
: __base_(allocator_arg_t(), __a, __from_tuple(), std::move(__p)) {}
848850

849851
# if _LIBCPP_STD_VER >= 23
850852
// tuple(const pair<U1, U2>&&) constructors (including allocator_arg_t variants)
851853

852854
template <class _U1, class _U2, enable_if_t< _EnableCtorFromPair<const pair<_U1, _U2>&&>::value>* = nullptr>
853855
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_BothImplicitlyConvertible<const pair<_U1, _U2>&&>::value)
854856
tuple(const pair<_U1, _U2>&& __p)
855-
: __base_(std::move(__p)) {}
857+
: __base_(__from_tuple(), std::move(__p)) {}
856858

857859
template <class _Alloc,
858860
class _U1,
859861
class _U2,
860862
enable_if_t< _EnableCtorFromPair<const pair<_U1, _U2>&&>::value>* = nullptr>
861863
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!_BothImplicitlyConvertible<const pair<_U1, _U2>&&>::value)
862864
tuple(allocator_arg_t, const _Alloc& __alloc, const pair<_U1, _U2>&& __p)
863-
: __base_(allocator_arg_t(), __alloc, std::move(__p)) {}
865+
: __base_(allocator_arg_t(), __alloc, __from_tuple(), std::move(__p)) {}
864866
# endif // _LIBCPP_STD_VER >= 23
865867

866868
// [tuple.assign]
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// Ensure that tuple's move constructor properly SFINAES.
10+
// This is a regression test for https://github.com/llvm/llvm-project/pull/151654#issuecomment-3205410955
11+
12+
// UNSUPPORTED: c++03, c++11, c++14
13+
14+
#include <tuple>
15+
#include <variant>
16+
#include <type_traits>
17+
18+
struct S {
19+
S(const S&) = delete;
20+
S& operator=(const S&) = delete;
21+
S(S&&) = default;
22+
S& operator=(S&&) = default;
23+
};
24+
25+
using T = std::tuple<const std::variant<S>>;
26+
27+
void func() { (void)std::is_trivially_move_constructible<T>::value; }

0 commit comments

Comments
 (0)