aboutsummaryrefslogtreecommitdiff
path: root/libcxx/include/tuple
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/include/tuple')
-rw-r--r--libcxx/include/tuple472
1 files changed, 338 insertions, 134 deletions
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 5cf120fec359..221eb23dd3f8 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -25,14 +25,24 @@ public:
explicit(see-below) tuple(U&&...); // constexpr in C++14
tuple(const tuple&) = default;
tuple(tuple&&) = default;
+
+ template<class... UTypes>
+ constexpr explicit(see-below) tuple(tuple<UTypes...>&); // C++23
template <class... U>
explicit(see-below) tuple(const tuple<U...>&); // constexpr in C++14
template <class... U>
explicit(see-below) tuple(tuple<U...>&&); // constexpr in C++14
+ template<class... UTypes>
+ constexpr explicit(see-below) tuple(const tuple<UTypes...>&&); // C++23
+
+ template<class U1, class U2>
+ constexpr explicit(see-below) tuple(pair<U1, U2>&); // iff sizeof...(Types) == 2 // C++23
template <class U1, class U2>
explicit(see-below) tuple(const pair<U1, U2>&); // iff sizeof...(T) == 2 // constexpr in C++14
template <class U1, class U2>
explicit(see-below) tuple(pair<U1, U2>&&); // iff sizeof...(T) == 2 // constexpr in C++14
+ template<class U1, class U2>
+ constexpr explicit(see-below) tuple(const pair<U1, U2>&&); // iff sizeof...(Types) == 2 // C++23
// allocator-extended constructors
template <class Alloc>
@@ -45,25 +55,47 @@ public:
tuple(allocator_arg_t, const Alloc& a, const tuple&); // constexpr in C++20
template <class Alloc>
tuple(allocator_arg_t, const Alloc& a, tuple&&); // constexpr in C++20
+ template<class Alloc, class... UTypes>
+ constexpr explicit(see-below)
+ tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&); // C++23
template <class Alloc, class... U>
explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const tuple<U...>&); // constexpr in C++20
template <class Alloc, class... U>
explicit(see-below) tuple(allocator_arg_t, const Alloc& a, tuple<U...>&&); // constexpr in C++20
+ template<class Alloc, class... UTypes>
+ constexpr explicit(see-below)
+ tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&&); // C++23
+ template<class Alloc, class U1, class U2>
+ constexpr explicit(see-below)
+ tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&); // C++23
template <class Alloc, class U1, class U2>
explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); // constexpr in C++20
template <class Alloc, class U1, class U2>
explicit(see-below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&); // constexpr in C++20
+ template<class Alloc, class U1, class U2>
+ constexpr explicit(see-below)
+ tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&&); // C++23
tuple& operator=(const tuple&); // constexpr in C++20
+ constexpr const tuple& operator=(const tuple&) const; // C++23
tuple& operator=(tuple&&) noexcept(is_nothrow_move_assignable_v<T> && ...); // constexpr in C++20
+ constexpr const tuple& operator=(tuple&&) const; // C++23
template <class... U>
tuple& operator=(const tuple<U...>&); // constexpr in C++20
+ template<class... UTypes>
+ constexpr const tuple& operator=(const tuple<UTypes...>&) const; // C++23
template <class... U>
tuple& operator=(tuple<U...>&&); // constexpr in C++20
+ template<class... UTypes>
+ constexpr const tuple& operator=(tuple<UTypes...>&&) const; // C++23
template <class U1, class U2>
tuple& operator=(const pair<U1, U2>&); // iff sizeof...(T) == 2 // constexpr in C++20
+ template<class U1, class U2>
+ constexpr const tuple& operator=(const pair<U1, U2>&) const; // iff sizeof...(Types) == 2 // C++23
template <class U1, class U2>
tuple& operator=(pair<U1, U2>&&); // iff sizeof...(T) == 2 // constexpr in C++20
+ template<class U1, class U2>
+ constexpr const tuple& operator=(pair<U1, U2>&&) const; // iff sizeof...(Types) == 2 // C++23
template<class U, size_t N>
tuple& operator=(array<U, N> const&) // iff sizeof...(T) == N, EXTENSION
@@ -71,6 +103,7 @@ public:
tuple& operator=(array<U, N>&&) // iff sizeof...(T) == N, EXTENSION
void swap(tuple&) noexcept(AND(swap(declval<T&>(), declval<T&>())...)); // constexpr in C++20
+ constexpr void swap(const tuple&) const noexcept(see-below); // C++23
};
@@ -161,29 +194,44 @@ template <class... Types>
void
swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(noexcept(x.swap(y)));
+template <class... Types>
+ constexpr void swap(const tuple<Types...>& x, const tuple<Types...>& y) noexcept(see-below); // C++23
+
} // std
*/
+#include <__assert> // all public C++ headers provide the assertion handler
#include <__compare/common_comparison_category.h>
#include <__compare/synth_three_way.h>
#include <__config>
#include <__functional/unwrap_ref.h>
-#include <__functional_base>
#include <__memory/allocator_arg_t.h>
#include <__memory/uses_allocator.h>
#include <__tuple>
#include <__utility/forward.h>
#include <__utility/integer_sequence.h>
#include <__utility/move.h>
-#include <compare>
+#include <__utility/pair.h>
+#include <__utility/piecewise_construct.h>
+#include <__utility/swap.h>
#include <cstddef>
#include <type_traits>
-#include <utility>
#include <version>
+#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
+# include <exception>
+# include <iosfwd>
+# include <new>
+# include <typeinfo>
+# include <utility>
+#endif
+
+// standard-mandated includes
+#include <compare>
+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#pragma GCC system_header
+# pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -206,6 +254,13 @@ void swap(__tuple_leaf<_Ip, _Hp, _Ep>& __x, __tuple_leaf<_Ip, _Hp, _Ep>& __y)
swap(__x.get(), __y.get());
}
+template <size_t _Ip, class _Hp, bool _Ep>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+void swap(const __tuple_leaf<_Ip, _Hp, _Ep>& __x, const __tuple_leaf<_Ip, _Hp, _Ep>& __y)
+ _NOEXCEPT_(__is_nothrow_swappable<const _Hp>::value) {
+ swap(__x.get(), __y.get());
+}
+
template <size_t _Ip, class _Hp, bool>
class __tuple_leaf
{
@@ -294,6 +349,12 @@ public:
return 0;
}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ int swap(const __tuple_leaf& __t) const _NOEXCEPT_(__is_nothrow_swappable<const __tuple_leaf>::value) {
+ _VSTD::swap(*this, __t);
+ return 0;
+ }
+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 _Hp& get() _NOEXCEPT {return __value_;}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const _Hp& get() const _NOEXCEPT {return __value_;}
};
@@ -360,6 +421,12 @@ public:
return 0;
}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ int swap(const __tuple_leaf& __rhs) const _NOEXCEPT_(__is_nothrow_swappable<const __tuple_leaf>::value) {
+ _VSTD::swap(*this, __rhs);
+ return 0;
+ }
+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 _Hp& get() _NOEXCEPT {return static_cast<_Hp&>(*this);}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const _Hp& get() const _NOEXCEPT {return static_cast<const _Hp&>(*this);}
};
@@ -450,6 +517,13 @@ struct _LIBCPP_DECLSPEC_EMPTY_BASES __tuple_impl<__tuple_indices<_Indx...>, _Tp.
{
_VSTD::__swallow(__tuple_leaf<_Indx, _Tp>::swap(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t))...);
}
+
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ void swap(const __tuple_impl& __t) const
+ _NOEXCEPT_(__all<__is_nothrow_swappable<const _Tp>::value...>::value)
+ {
+ _VSTD::__swallow(__tuple_leaf<_Indx, _Tp>::swap(static_cast<const __tuple_leaf<_Indx, _Tp>&>(__t))...);
+ }
};
template<class _Dest, class _Source, size_t ..._Np>
@@ -685,6 +759,7 @@ public:
template <class _Alloc, template<class...> class _And = _And, __enable_if_t<
_And<is_copy_constructible<_Tp>...>::value
, int> = 0>
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
tuple(allocator_arg_t, const _Alloc& __alloc, const tuple& __t)
: __base_(allocator_arg_t(), __alloc, __t)
{ }
@@ -692,30 +767,39 @@ public:
template <class _Alloc, template<class...> class _And = _And, __enable_if_t<
_And<is_move_constructible<_Tp>...>::value
, int> = 0>
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
tuple(allocator_arg_t, const _Alloc& __alloc, tuple&& __t)
: __base_(allocator_arg_t(), __alloc, _VSTD::move(__t))
{ }
// tuple(const tuple<U...>&) constructors (including allocator_arg_t variants)
- template <class ..._Up>
- struct _EnableCopyFromOtherTuple : _And<
- _Not<is_same<tuple<_Tp...>, tuple<_Up...> > >,
- _Lazy<_Or,
- _BoolConstant<sizeof...(_Tp) != 1>,
+
+ template <class _OtherTuple, class _DecayedOtherTuple = __uncvref_t<_OtherTuple>, class = void>
+ struct _EnableCtorFromUTypesTuple : false_type {};
+
+ template <class _OtherTuple, class... _Up>
+ struct _EnableCtorFromUTypesTuple<_OtherTuple, tuple<_Up...>,
+ // the length of the packs needs to checked first otherwise the 2 packs cannot be expanded simultaneously below
+ __enable_if_t<sizeof...(_Up) == sizeof...(_Tp)>> : _And<
+ // the two conditions below are not in spec. The purpose is to disable the UTypes Ctor when copy/move Ctor can work.
+ // Otherwise, is_constructible can trigger hard error in those cases https://godbolt.org/z/M94cGdKcE
+ _Not<is_same<_OtherTuple, const tuple&> >,
+ _Not<is_same<_OtherTuple, tuple&&> >,
+ is_constructible<_Tp, __copy_cvref_t<_OtherTuple, _Up> >...,
+ _Lazy<_Or, _BoolConstant<sizeof...(_Tp) != 1>,
// _Tp and _Up are 1-element packs - the pack expansions look
// weird to avoid tripping up the type traits in degenerate cases
_Lazy<_And,
- _Not<is_convertible<const tuple<_Up>&, _Tp> >...,
- _Not<is_constructible<_Tp, const tuple<_Up>&> >...
+ _Not<is_same<_Tp, _Up> >...,
+ _Not<is_convertible<_OtherTuple, _Tp> >...,
+ _Not<is_constructible<_Tp, _OtherTuple> >...
>
- >,
- is_constructible<_Tp, const _Up&>...
- > { };
+ >
+ > {};
template <class ..._Up, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
- _EnableCopyFromOtherTuple<_Up...>,
+ _EnableCtorFromUTypesTuple<const tuple<_Up...>&>,
is_convertible<const _Up&, _Tp>... // explicit check
>::value
, int> = 0>
@@ -727,8 +811,7 @@ public:
template <class ..._Up, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
- _EnableCopyFromOtherTuple<_Up...>,
+ _EnableCtorFromUTypesTuple<const tuple<_Up...>&>,
_Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> > // explicit check
>::value
, int> = 0>
@@ -740,8 +823,7 @@ public:
template <class ..._Up, class _Alloc, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
- _EnableCopyFromOtherTuple<_Up...>,
+ _EnableCtorFromUTypesTuple<const tuple<_Up...>&>,
is_convertible<const _Up&, _Tp>... // explicit check
>::value
, int> = 0>
@@ -752,8 +834,7 @@ public:
template <class ..._Up, class _Alloc, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
- _EnableCopyFromOtherTuple<_Up...>,
+ _EnableCtorFromUTypesTuple<const tuple<_Up...>&>,
_Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> > // explicit check
>::value
, int> = 0>
@@ -762,26 +843,27 @@ public:
: __base_(allocator_arg_t(), __a, __t)
{ }
+#if _LIBCPP_STD_VER > 20
+ // 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(!(is_convertible_v<_Up&, _Tp> && ...))
+ tuple(tuple<_Up...>& __t) : __base_(__t) {}
+
+ template <class _Alloc, class... _Up, enable_if_t<
+ _EnableCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ explicit(!(is_convertible_v<_Up&, _Tp> && ...))
+ tuple(allocator_arg_t, const _Alloc& __alloc, tuple<_Up...>& __t) : __base_(allocator_arg_t(), __alloc, __t) {}
+#endif // _LIBCPP_STD_VER > 20
+
// tuple(tuple<U...>&&) constructors (including allocator_arg_t variants)
- template <class ..._Up>
- struct _EnableMoveFromOtherTuple : _And<
- _Not<is_same<tuple<_Tp...>, tuple<_Up...> > >,
- _Lazy<_Or,
- _BoolConstant<sizeof...(_Tp) != 1>,
- // _Tp and _Up are 1-element packs - the pack expansions look
- // weird to avoid tripping up the type traits in degenerate cases
- _Lazy<_And,
- _Not<is_convertible<tuple<_Up>, _Tp> >...,
- _Not<is_constructible<_Tp, tuple<_Up> > >...
- >
- >,
- is_constructible<_Tp, _Up>...
- > { };
template <class ..._Up, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
- _EnableMoveFromOtherTuple<_Up...>,
+ _EnableCtorFromUTypesTuple<tuple<_Up...>&&>,
is_convertible<_Up, _Tp>... // explicit check
>::value
, int> = 0>
@@ -793,8 +875,7 @@ public:
template <class ..._Up, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
- _EnableMoveFromOtherTuple<_Up...>,
+ _EnableCtorFromUTypesTuple<tuple<_Up...>&&>,
_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> > // explicit check
>::value
, int> = 0>
@@ -806,8 +887,7 @@ public:
template <class _Alloc, class ..._Up, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
- _EnableMoveFromOtherTuple<_Up...>,
+ _EnableCtorFromUTypesTuple<tuple<_Up...>&&>,
is_convertible<_Up, _Tp>... // explicit check
>::value
, int> = 0>
@@ -818,8 +898,7 @@ public:
template <class _Alloc, class ..._Up, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
- _EnableMoveFromOtherTuple<_Up...>,
+ _EnableCtorFromUTypesTuple<tuple<_Up...>&&>,
_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> > // explicit check
>::value
, int> = 0>
@@ -828,57 +907,77 @@ public:
: __base_(allocator_arg_t(), __a, _VSTD::move(__t))
{ }
+#if _LIBCPP_STD_VER > 20
+ // tuple(const tuple<U...>&&) constructors (including allocator_arg_t variants)
+
+ template <class... _Up, enable_if_t<
+ _EnableCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ explicit(!(is_convertible_v<const _Up&&, _Tp> && ...))
+ tuple(const tuple<_Up...>&& __t) : __base_(std::move(__t)) {}
+
+ template <class _Alloc, class... _Up, enable_if_t<
+ _EnableCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ explicit(!(is_convertible_v<const _Up&&, _Tp> && ...))
+ tuple(allocator_arg_t, const _Alloc& __alloc, const tuple<_Up...>&& __t)
+ : __base_(allocator_arg_t(), __alloc, std::move(__t)) {}
+#endif // _LIBCPP_STD_VER > 20
+
// tuple(const pair<U1, U2>&) constructors (including allocator_arg_t variants)
- template <class _Up1, class _Up2, class ..._DependentTp>
- struct _EnableImplicitCopyFromPair : _And<
- is_constructible<_FirstType<_DependentTp...>, const _Up1&>,
- is_constructible<_SecondType<_DependentTp...>, const _Up2&>,
- is_convertible<const _Up1&, _FirstType<_DependentTp...> >, // explicit check
- is_convertible<const _Up2&, _SecondType<_DependentTp...> >
- > { };
- template <class _Up1, class _Up2, class ..._DependentTp>
- struct _EnableExplicitCopyFromPair : _And<
- is_constructible<_FirstType<_DependentTp...>, const _Up1&>,
- is_constructible<_SecondType<_DependentTp...>, const _Up2&>,
- _Not<is_convertible<const _Up1&, _FirstType<_DependentTp...> > >, // explicit check
- _Not<is_convertible<const _Up2&, _SecondType<_DependentTp...> > >
- > { };
+ template <template <class...> class Pred, class _Pair, class _DecayedPair = __uncvref_t<_Pair>, class _Tuple = tuple>
+ struct _CtorPredicateFromPair : false_type{};
+
+ template <template <class...> class Pred, class _Pair, class _Up1, class _Up2, class _Tp1, class _Tp2>
+ struct _CtorPredicateFromPair<Pred, _Pair, pair<_Up1, _Up2>, tuple<_Tp1, _Tp2> > : _And<
+ Pred<_Tp1, __copy_cvref_t<_Pair, _Up1> >,
+ Pred<_Tp2, __copy_cvref_t<_Pair, _Up2> >
+ > {};
+
+ template <class _Pair>
+ struct _EnableCtorFromPair : _CtorPredicateFromPair<is_constructible, _Pair>{};
+
+ template <class _Pair>
+ struct _NothrowConstructibleFromPair : _CtorPredicateFromPair<is_nothrow_constructible, _Pair>{};
+
+ template <class _Pair, class _DecayedPair = __uncvref_t<_Pair>, class _Tuple = tuple>
+ struct _BothImplicitlyConvertible : false_type{};
+
+ template <class _Pair, class _Up1, class _Up2, class _Tp1, class _Tp2>
+ struct _BothImplicitlyConvertible<_Pair, pair<_Up1, _Up2>, tuple<_Tp1, _Tp2> > : _And<
+ is_convertible<__copy_cvref_t<_Pair, _Up1>, _Tp1>,
+ is_convertible<__copy_cvref_t<_Pair, _Up2>, _Tp2>
+ > {};
template <class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Tp) == 2>,
- _EnableImplicitCopyFromPair<_Up1, _Up2, _Tp...>
+ _EnableCtorFromPair<const pair<_Up1, _Up2>&>,
+ _BothImplicitlyConvertible<const pair<_Up1, _Up2>&> // explicit check
>::value
, int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
tuple(const pair<_Up1, _Up2>& __p)
- _NOEXCEPT_((_And<
- is_nothrow_constructible<_FirstType<_Tp...>, const _Up1&>,
- is_nothrow_constructible<_SecondType<_Tp...>, const _Up2&>
- >::value))
+ _NOEXCEPT_((_NothrowConstructibleFromPair<const pair<_Up1, _Up2>&>::value))
: __base_(__p)
{ }
template <class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Tp) == 2>,
- _EnableExplicitCopyFromPair<_Up1, _Up2, _Tp...>
+ _EnableCtorFromPair<const pair<_Up1, _Up2>&>,
+ _Not<_BothImplicitlyConvertible<const pair<_Up1, _Up2>&> > // explicit check
>::value
, int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
explicit tuple(const pair<_Up1, _Up2>& __p)
- _NOEXCEPT_((_And<
- is_nothrow_constructible<_FirstType<_Tp...>, const _Up1&>,
- is_nothrow_constructible<_SecondType<_Tp...>, const _Up2&>
- >::value))
+ _NOEXCEPT_((_NothrowConstructibleFromPair<const pair<_Up1, _Up2>&>::value))
: __base_(__p)
{ }
template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Tp) == 2>,
- _EnableImplicitCopyFromPair<_Up1, _Up2, _Tp...>
+ _EnableCtorFromPair<const pair<_Up1, _Up2>&>,
+ _BothImplicitlyConvertible<const pair<_Up1, _Up2>&> // explicit check
>::value
, int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
@@ -888,8 +987,8 @@ public:
template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Tp) == 2>,
- _EnableExplicitCopyFromPair<_Up1, _Up2, _Tp...>
+ _EnableCtorFromPair<const pair<_Up1, _Up2>&>,
+ _Not<_BothImplicitlyConvertible<const pair<_Up1, _Up2>&> > // explicit check
>::value
, int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
@@ -897,57 +996,52 @@ public:
: __base_(allocator_arg_t(), __a, __p)
{ }
- // tuple(pair<U1, U2>&&) constructors (including allocator_arg_t variants)
- template <class _Up1, class _Up2, class ..._DependentTp>
- struct _EnableImplicitMoveFromPair : _And<
- is_constructible<_FirstType<_DependentTp...>, _Up1>,
- is_constructible<_SecondType<_DependentTp...>, _Up2>,
- is_convertible<_Up1, _FirstType<_DependentTp...> >, // explicit check
- is_convertible<_Up2, _SecondType<_DependentTp...> >
- > { };
+#if _LIBCPP_STD_VER > 20
+ // tuple(pair<U1, U2>&) constructors (including allocator_arg_t variants)
- template <class _Up1, class _Up2, class ..._DependentTp>
- struct _EnableExplicitMoveFromPair : _And<
- is_constructible<_FirstType<_DependentTp...>, _Up1>,
- is_constructible<_SecondType<_DependentTp...>, _Up2>,
- _Not<is_convertible<_Up1, _FirstType<_DependentTp...> > >, // explicit check
- _Not<is_convertible<_Up2, _SecondType<_DependentTp...> > >
- > { };
+ 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) {}
+
+ template <class _Alloc, class _U1, class _U2, 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) {}
+#endif
+
+ // tuple(pair<U1, U2>&&) constructors (including allocator_arg_t variants)
template <class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Tp) == 2>,
- _EnableImplicitMoveFromPair<_Up1, _Up2, _Tp...>
+ _EnableCtorFromPair<pair<_Up1, _Up2>&&>,
+ _BothImplicitlyConvertible<pair<_Up1, _Up2>&&> // explicit check
>::value
, int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
tuple(pair<_Up1, _Up2>&& __p)
- _NOEXCEPT_((_And<
- is_nothrow_constructible<_FirstType<_Tp...>, _Up1>,
- is_nothrow_constructible<_SecondType<_Tp...>, _Up2>
- >::value))
+ _NOEXCEPT_((_NothrowConstructibleFromPair<pair<_Up1, _Up2>&&>::value))
: __base_(_VSTD::move(__p))
{ }
template <class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Tp) == 2>,
- _EnableExplicitMoveFromPair<_Up1, _Up2, _Tp...>
+ _EnableCtorFromPair<pair<_Up1, _Up2>&&>,
+ _Not<_BothImplicitlyConvertible<pair<_Up1, _Up2>&&> > // explicit check
>::value
, int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
explicit tuple(pair<_Up1, _Up2>&& __p)
- _NOEXCEPT_((_And<
- is_nothrow_constructible<_FirstType<_Tp...>, _Up1>,
- is_nothrow_constructible<_SecondType<_Tp...>, _Up2>
- >::value))
+ _NOEXCEPT_((_NothrowConstructibleFromPair<pair<_Up1, _Up2>&&>::value))
: __base_(_VSTD::move(__p))
{ }
template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Tp) == 2>,
- _EnableImplicitMoveFromPair<_Up1, _Up2, _Tp...>
+ _EnableCtorFromPair<pair<_Up1, _Up2>&&>,
+ _BothImplicitlyConvertible<pair<_Up1, _Up2>&&> // explicit check
>::value
, int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
@@ -957,8 +1051,8 @@ public:
template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
_And<
- _BoolConstant<sizeof...(_Tp) == 2>,
- _EnableExplicitMoveFromPair<_Up1, _Up2, _Tp...>
+ _EnableCtorFromPair<pair<_Up1, _Up2>&&>,
+ _Not<_BothImplicitlyConvertible<pair<_Up1, _Up2>&&> > // explicit check
>::value
, int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
@@ -966,6 +1060,23 @@ public:
: __base_(allocator_arg_t(), __a, _VSTD::move(__p))
{ }
+#if _LIBCPP_STD_VER > 20
+ // tuple(const pair<U1, U2>&&) constructors (including allocator_arg_t variants)
+
+ 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)) {}
+
+ template <class _Alloc, 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(allocator_arg_t, const _Alloc& __alloc, const pair<_U1, _U2>&& __p)
+ : __base_(allocator_arg_t(), __alloc, std::move(__p)) {}
+#endif // _LIBCPP_STD_VER > 20
+
// [tuple.assign]
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
tuple& operator=(_If<_And<is_copy_assignable<_Tp>...>::value, tuple, __nat> const& __tuple)
@@ -976,6 +1087,25 @@ public:
return *this;
}
+#if _LIBCPP_STD_VER > 20
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ const tuple& operator=(tuple const& __tuple) const
+ requires (_And<is_copy_assignable<const _Tp>...>::value) {
+ std::__memberwise_copy_assign(*this, __tuple, typename __make_tuple_indices<sizeof...(_Tp)>::type());
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ const tuple& operator=(tuple&& __tuple) const
+ requires (_And<is_assignable<const _Tp&, _Tp>...>::value) {
+ std::__memberwise_forward_assign(*this,
+ std::move(__tuple),
+ __tuple_types<_Tp...>(),
+ typename __make_tuple_indices<sizeof...(_Tp)>::type());
+ return *this;
+ }
+#endif // _LIBCPP_STD_VER > 20
+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
tuple& operator=(_If<_And<is_move_assignable<_Tp>...>::value, tuple, __nat>&& __tuple)
_NOEXCEPT_((_And<is_nothrow_move_assignable<_Tp>...>::value))
@@ -1017,38 +1147,89 @@ public:
return *this;
}
- template<class _Up1, class _Up2, class _Dep = true_type, __enable_if_t<
- _And<_Dep,
- _BoolConstant<sizeof...(_Tp) == 2>,
- is_assignable<_FirstType<_Tp..., _Dep>&, _Up1 const&>,
- is_assignable<_SecondType<_Tp..., _Dep>&, _Up2 const&>
- >::value
+
+#if _LIBCPP_STD_VER > 20
+ template <class... _UTypes, enable_if_t<
+ _And<_BoolConstant<sizeof...(_Tp) == sizeof...(_UTypes)>,
+ is_assignable<const _Tp&, const _UTypes&>...>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ const tuple& operator=(const tuple<_UTypes...>& __u) const {
+ std::__memberwise_copy_assign(*this,
+ __u,
+ typename __make_tuple_indices<sizeof...(_Tp)>::type());
+ return *this;
+ }
+
+ template <class... _UTypes, enable_if_t<
+ _And<_BoolConstant<sizeof...(_Tp) == sizeof...(_UTypes)>,
+ is_assignable<const _Tp&, _UTypes>...>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ const tuple& operator=(tuple<_UTypes...>&& __u) const {
+ std::__memberwise_forward_assign(*this,
+ __u,
+ __tuple_types<_UTypes...>(),
+ typename __make_tuple_indices<sizeof...(_Tp)>::type());
+ return *this;
+ }
+#endif // _LIBCPP_STD_VER > 20
+
+ template <template<class...> class Pred, bool _Const,
+ class _Pair, class _DecayedPair = __uncvref_t<_Pair>, class _Tuple = tuple>
+ struct _AssignPredicateFromPair : false_type {};
+
+ template <template<class...> class Pred, bool _Const,
+ class _Pair, class _Up1, class _Up2, class _Tp1, class _Tp2>
+ struct _AssignPredicateFromPair<Pred, _Const, _Pair, pair<_Up1, _Up2>, tuple<_Tp1, _Tp2> > :
+ _And<Pred<__maybe_const<_Const, _Tp1>&, __copy_cvref_t<_Pair, _Up1> >,
+ Pred<__maybe_const<_Const, _Tp2>&, __copy_cvref_t<_Pair, _Up2> >
+ > {};
+
+ template <bool _Const, class _Pair>
+ struct _EnableAssignFromPair : _AssignPredicateFromPair<is_assignable, _Const, _Pair> {};
+
+ template <bool _Const, class _Pair>
+ struct _NothrowAssignFromPair : _AssignPredicateFromPair<is_nothrow_assignable, _Const, _Pair> {};
+
+#if _LIBCPP_STD_VER > 20
+ template <class _U1, class _U2, enable_if_t<
+ _EnableAssignFromPair<true, const pair<_U1, _U2>&>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ const tuple& operator=(const pair<_U1, _U2>& __pair) const
+ noexcept(_NothrowAssignFromPair<true, const pair<_U1, _U2>&>::value) {
+ std::get<0>(*this) = __pair.first;
+ std::get<1>(*this) = __pair.second;
+ return *this;
+ }
+
+ template <class _U1, class _U2, enable_if_t<
+ _EnableAssignFromPair<true, pair<_U1, _U2>&&>::value>* = nullptr>
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ const tuple& operator=(pair<_U1, _U2>&& __pair) const
+ noexcept(_NothrowAssignFromPair<true, pair<_U1, _U2>&&>::value) {
+ std::get<0>(*this) = std::move(__pair.first);
+ std::get<1>(*this) = std::move(__pair.second);
+ return *this;
+ }
+#endif // _LIBCPP_STD_VER > 20
+
+ template<class _Up1, class _Up2, __enable_if_t<
+ _EnableAssignFromPair<false, pair<_Up1, _Up2> const&>::value
,int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
tuple& operator=(pair<_Up1, _Up2> const& __pair)
- _NOEXCEPT_((_And<
- is_nothrow_assignable<_FirstType<_Tp...>&, _Up1 const&>,
- is_nothrow_assignable<_SecondType<_Tp...>&, _Up2 const&>
- >::value))
+ _NOEXCEPT_((_NothrowAssignFromPair<false, pair<_Up1, _Up2> const&>::value))
{
_VSTD::get<0>(*this) = __pair.first;
_VSTD::get<1>(*this) = __pair.second;
return *this;
}
- template<class _Up1, class _Up2, class _Dep = true_type, __enable_if_t<
- _And<_Dep,
- _BoolConstant<sizeof...(_Tp) == 2>,
- is_assignable<_FirstType<_Tp..., _Dep>&, _Up1>,
- is_assignable<_SecondType<_Tp..., _Dep>&, _Up2>
- >::value
+ template<class _Up1, class _Up2, __enable_if_t<
+ _EnableAssignFromPair<false, pair<_Up1, _Up2>&&>::value
,int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
tuple& operator=(pair<_Up1, _Up2>&& __pair)
- _NOEXCEPT_((_And<
- is_nothrow_assignable<_FirstType<_Tp...>&, _Up1>,
- is_nothrow_assignable<_SecondType<_Tp...>&, _Up2>
- >::value))
+ _NOEXCEPT_((_NothrowAssignFromPair<false, pair<_Up1, _Up2>&&>::value))
{
_VSTD::get<0>(*this) = _VSTD::forward<_Up1>(__pair.first);
_VSTD::get<1>(*this) = _VSTD::forward<_Up2>(__pair.second);
@@ -1092,6 +1273,13 @@ public:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
void swap(tuple& __t) _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
{__base_.swap(__t.__base_);}
+
+#if _LIBCPP_STD_VER > 20
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ void swap(const tuple& __t) const noexcept(__all<is_nothrow_swappable_v<const _Tp&>...>::value) {
+ __base_.swap(__t.__base_);
+ }
+#endif // _LIBCPP_STD_VER > 20
};
template <>
@@ -1114,6 +1302,9 @@ public:
tuple(allocator_arg_t, const _Alloc&, array<_Up, 0>) _NOEXCEPT {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
void swap(tuple&) _NOEXCEPT {}
+#if _LIBCPP_STD_VER > 20
+ _LIBCPP_HIDE_FROM_ABI constexpr void swap(const tuple&) const noexcept {}
+#endif
};
#if _LIBCPP_STD_VER > 20
@@ -1128,7 +1319,7 @@ template <class... _TTypes, class... _UTypes>
struct common_type<tuple<_TTypes...>, tuple<_UTypes...>> {
using type = tuple<common_type_t<_TTypes, _UTypes>...>;
};
-#endif
+#endif // _LIBCPP_STD_VER > 20
#if _LIBCPP_STD_VER > 14
template <class ..._Tp>
@@ -1154,6 +1345,16 @@ swap(tuple<_Tp...>& __t, tuple<_Tp...>& __u)
_NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
{__t.swap(__u);}
+#if _LIBCPP_STD_VER > 20
+template <class... _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr
+enable_if_t<__all<is_swappable_v<const _Tp>...>::value, void>
+swap(const tuple<_Tp...>& __lhs, const tuple<_Tp...>& __rhs)
+ noexcept(__all<is_nothrow_swappable_v<const _Tp>...>::value) {
+ __lhs.swap(__rhs);
+}
+#endif
+
// get
template <size_t _Ip, class ..._Tp>
@@ -1333,7 +1534,7 @@ operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
return __tuple_equal<sizeof...(_Tp)>()(__x, __y);
}
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
+#if _LIBCPP_STD_VER > 17
// operator<=>
@@ -1355,7 +1556,7 @@ operator<=>(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
return _VSTD::__tuple_compare_three_way(__x, __y, index_sequence_for<_Tp...>{});
}
-#else // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
+#else // _LIBCPP_STD_VER > 17
template <class ..._Tp, class ..._Up>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
@@ -1425,7 +1626,7 @@ operator<=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
return !(__y < __x);
}
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
+#endif // _LIBCPP_STD_VER > 17
// tuple_cat
@@ -1445,9 +1646,10 @@ struct __tuple_cat_return_1
template <class ..._Types, class _Tuple0>
struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0>
{
- typedef _LIBCPP_NODEBUG typename __tuple_cat_type<tuple<_Types...>,
- typename __make_tuple_types<typename __uncvref<_Tuple0>::type>::type>::type
- type;
+ using type _LIBCPP_NODEBUG = typename __tuple_cat_type<
+ tuple<_Types...>,
+ typename __make_tuple_types<__uncvref_t<_Tuple0> >::type
+ >::type;
};
template <class ..._Types, class _Tuple0, class _Tuple1, class ..._Tuples>
@@ -1455,7 +1657,7 @@ struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0, _Tuple1, _Tuples...
: public __tuple_cat_return_1<
typename __tuple_cat_type<
tuple<_Types...>,
- typename __make_tuple_types<typename __uncvref<_Tuple0>::type>::type
+ typename __make_tuple_types<__uncvref_t<_Tuple0> >::type
>::type,
__tuple_like<typename remove_reference<_Tuple1>::type>::value,
_Tuple1, _Tuples...>
@@ -1529,6 +1731,7 @@ struct __tuple_cat<tuple<_Types...>, __tuple_indices<_I0...>, __tuple_indices<_J
typename __tuple_cat_return_ref<tuple<_Types...>&&, _Tuple0&&>::type
operator()(tuple<_Types...> __t, _Tuple0&& __t0)
{
+ (void)__t; // avoid unused parameter warning on GCC when _I0 is empty
return _VSTD::forward_as_tuple(
_VSTD::forward<_Types>(_VSTD::get<_I0>(__t))...,
_VSTD::get<_J0>(_VSTD::forward<_Tuple0>(__t0))...);
@@ -1539,6 +1742,7 @@ struct __tuple_cat<tuple<_Types...>, __tuple_indices<_I0...>, __tuple_indices<_J
typename __tuple_cat_return_ref<tuple<_Types...>&&, _Tuple0&&, _Tuple1&&, _Tuples&&...>::type
operator()(tuple<_Types...> __t, _Tuple0&& __t0, _Tuple1&& __t1, _Tuples&& ...__tpls)
{
+ (void)__t; // avoid unused parameter warning on GCC when _I0 is empty
typedef _LIBCPP_NODEBUG typename remove_reference<_Tuple0>::type _T0;
typedef _LIBCPP_NODEBUG typename remove_reference<_Tuple1>::type _T1;
return __tuple_cat<
@@ -1593,7 +1797,7 @@ inline _LIBCPP_INLINE_VISIBILITY
constexpr decltype(auto) __apply_tuple_impl(_Fn && __f, _Tuple && __t,
__tuple_indices<_Id...>)
_LIBCPP_NOEXCEPT_RETURN(
- _VSTD::__invoke_constexpr(
+ _VSTD::__invoke(
_VSTD::forward<_Fn>(__f),
_VSTD::get<_Id>(_VSTD::forward<_Tuple>(__t))...)
)