namespace std {
template<class... Types>
class tuple;
inline constexpr unspecified ignore;
template<class... TTypes>
constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&...);
template<class... TTypes>
constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&...) noexcept;
template<class... TTypes>
constexpr tuple<TTypes&...> tie(TTypes&...) noexcept;
template<class... Tuples>
constexpr tuple<CTypes...> tuple_cat(Tuples&&...);
template<class F, class Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t);
template<class T, class Tuple>
constexpr T make_from_tuple(Tuple&& t);
template<class T> class tuple_size;
template<class T> class tuple_size<const T>;
template<class T> class tuple_size<volatile T>;
template<class T> class tuple_size<const volatile T>;
template<class... Types> class tuple_size<tuple<Types...>>;
template<size_t I, class T> class tuple_element;
template<size_t I, class T> class tuple_element<I, const T>;
template<size_t I, class T> class tuple_element<I, volatile T>;
template<size_t I, class T> class tuple_element<I, const volatile T>;
template<size_t I, class... Types>
class tuple_element<I, tuple<Types...>>;
template<size_t I, class T>
using tuple_element_t = typename tuple_element<I, T>::type;
template<size_t I, class... Types>
constexpr tuple_element_t<I, tuple<Types...>>& get(tuple<Types...>&) noexcept;
template<size_t I, class... Types>
constexpr tuple_element_t<I, tuple<Types...>>&& get(tuple<Types...>&&) noexcept;
template<size_t I, class... Types>
constexpr const tuple_element_t<I, tuple<Types...>>& get(const tuple<Types...>&) noexcept;
template<size_t I, class... Types>
constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&&) noexcept;
template<class T, class... Types>
constexpr T& get(tuple<Types...>& t) noexcept;
template<class T, class... Types>
constexpr T&& get(tuple<Types...>&& t) noexcept;
template<class T, class... Types>
constexpr const T& get(const tuple<Types...>& t) noexcept;
template<class T, class... Types>
constexpr const T&& get(const tuple<Types...>&& t) noexcept;
template<class... TTypes, class... UTypes>
constexpr bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&);
template<class... TTypes, class... UTypes>
constexpr bool operator!=(const tuple<TTypes...>&, const tuple<UTypes...>&);
template<class... TTypes, class... UTypes>
constexpr bool operator<(const tuple<TTypes...>&, const tuple<UTypes...>&);
template<class... TTypes, class... UTypes>
constexpr bool operator>(const tuple<TTypes...>&, const tuple<UTypes...>&);
template<class... TTypes, class... UTypes>
constexpr bool operator<=(const tuple<TTypes...>&, const tuple<UTypes...>&);
template<class... TTypes, class... UTypes>
constexpr bool operator>=(const tuple<TTypes...>&, const tuple<UTypes...>&);
template<class... Types, class Alloc>
struct uses_allocator<tuple<Types...>, Alloc>;
template<class... Types>
constexpr void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
template<class T>
inline constexpr size_t tuple_size_v = tuple_size<T>::value;
}
namespace std {
template<class... Types>
class tuple {
public:
constexpr explicit(see below) tuple();
constexpr explicit(see below) tuple(const Types&...);
template<class... UTypes>
constexpr explicit(see below) tuple(UTypes&&...);
tuple(const tuple&) = default;
tuple(tuple&&) = default;
template<class... UTypes>
constexpr explicit(see below) tuple(const tuple<UTypes...>&);
template<class... UTypes>
constexpr explicit(see below) tuple(tuple<UTypes...>&&);
template<class U1, class U2>
constexpr explicit(see below) tuple(const pair<U1, U2>&);
template<class U1, class U2>
constexpr explicit(see below) tuple(pair<U1, U2>&&);
template<class Alloc>
constexpr tuple(allocator_arg_t, const Alloc& a);
template<class Alloc>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const Types&...);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
template<class Alloc>
constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&);
template<class Alloc>
constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
constexpr tuple& operator=(const tuple&);
constexpr tuple& operator=(tuple&&) noexcept(see below);
template<class... UTypes>
constexpr tuple& operator=(const tuple<UTypes...>&);
template<class... UTypes>
constexpr tuple& operator=(tuple<UTypes...>&&);
template<class U1, class U2>
constexpr tuple& operator=(const pair<U1, U2>&);
template<class U1, class U2>
constexpr tuple& operator=(pair<U1, U2>&&);
constexpr void swap(tuple&) noexcept(see below);
};
template<class... UTypes>
tuple(UTypes...) -> tuple<UTypes...>;
template<class T1, class T2>
tuple(pair<T1, T2>) -> tuple<T1, T2>;
template<class Alloc, class... UTypes>
tuple(allocator_arg_t, Alloc, UTypes...) -> tuple<UTypes...>;
template<class Alloc, class T1, class T2>
tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>;
template<class Alloc, class... UTypes>
tuple(allocator_arg_t, Alloc, tuple<UTypes...>) -> tuple<UTypes...>;
}
In the descriptions that follow, let
i be in the range
[0, sizeof...(Types)) in order,
Ti
be the
ith type in
Types, and
Ui be the
ith type in a template parameter pack named
UTypes, where indexing
is zero-based
.For each
tuple constructor, an exception is thrown only if the construction of
one of the types in
Types throws an exception
.The defaulted move and copy constructor, respectively, of
tuple shall be a constexpr function if and only if all
required element-wise initializations for copy and move, respectively,
would satisfy the requirements for a constexpr function
. The
defaulted move and copy constructor of
tuple<> shall be
constexpr functions
.If
is_trivially_destructible_v<Ti> is
true for all
Ti,
then the destructor of
tuple is trivial
. constexpr explicit(see below) tuple();
Effects: Value-initializes each element
. Remarks:
This constructor shall not participate in overload resolution unless
is_default_constructible_v<Ti> is
true for all
i. [
βNote: This behavior can be implemented by a constructor template
with default template arguments
. β
βend note β]
The expression inside
explicit evaluates to
true
if and only if
Ti is not implicitly
default-constructible for at least one
i. [
βNote: This behavior can be implemented with a trait that checks whether
a
const Ti& can be initialized with
{}. β
βend note β]
constexpr explicit(see below) tuple(const Types&...);
Effects: Initializes each element with the value of the
corresponding parameter
. Remarks: This constructor shall not participate in overload resolution unless
sizeof...(Types) >= 1 and
is_copy_constructible_v<Ti>
is
true for all
i. The expression inside
explicit is equivalent to:
!conjunction_v<is_convertible<const Types&, Types>...>
template<class... UTypes> constexpr explicit(see below) tuple(UTypes&&... u);
Effects: Initializes the elements in the tuple with the
corresponding value in
std::forward<UTypes>(u). Remarks: This constructor shall not participate in overload resolution unless
sizeof...(Types) == sizeof...(UTypes) and
sizeof...(Types) >= 1 and
is_constructible_v<Ti, Ui&&>
is
true for all
i. The expression inside
explicit is equivalent to:
!conjunction_v<is_convertible<UTypes, Types>...>
tuple(const tuple& u) = default;
Requires: is_copy_constructible_v<Ti> is
true for all
i. Effects: Initializes each element of
*this with the
corresponding element of
u. tuple(tuple&& u) = default;
Requires: is_move_constructible_v<Ti> is
true for all
i. Effects: For all
i, initializes the
ith element of
*this with
std::forward<Ti>(get<i>(u)). template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>& u);
Effects: Initializes each element of
*this
with the corresponding element of
u. Remarks: This constructor shall not participate in overload resolution unless
sizeof...(Types) == sizeof...(UTypes) and
is_constructible_v<Ti, const Ui&> is true for all i, and
either
sizeof...(Types) != 1, or
(when
Types... expands to
T and
UTypes... expands to
U)
is_convertible_v<const tuple<U>&, T>,
is_constructible_v<T, const tuple<U>&>, and
is_same_v<T, U> are all
false.
The expression inside
explicit is equivalent to:
!conjunction_v<is_convertible<const UTypes&, Types>...>
template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&& u);
Effects: For all
i,
initializes the
ith element of
*this with
std::forward<Ui>(get<i>(u)). Remarks: This constructor shall not participate in overload resolution unless
sizeof...(Types) == sizeof...(UTypes), and
is_constructible_v<Ti, Ui&&> is true for all i, and
either
sizeof...(Types) != 1, or
(when
Types... expands to
T and
UTypes... expands to
U)
is_convertible_v<tuple<U>, T>,
is_constructible_v<T, tuple<U>>,
and
is_same_v<T, U> are all
false.
The expression inside
explicit is equivalent to:
!conjunction_v<is_convertible<UTypes, Types>...>
template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>& u);
Effects: Initializes the first element with
u.first and the
second element with
u.second. Remarks: This constructor shall not participate in overload resolution unless
sizeof...(Types) == 2,
is_constructible_v<T0, const U1&> is
true and
is_constructible_v<T1, const U2&> is
true. The expression inside
explicit is equivalent to:
!is_convertible_v<const U1&, T0> || !is_convertible_v<const U2&, T1>
template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>&& u);
Effects: Initializes the first element with
std::forward<U1>(u.first) and the
second element with
std::forward<U2>(u.second). Remarks: This constructor shall not participate in overload resolution unless
sizeof...(Types) == 2,
is_constructible_v<T0, U1&&> is
true and
is_constructible_v<T1, U2&&> is
true. The expression inside
explicit is equivalent to:
!is_convertible_v<U1, T0> || !is_convertible_v<U2, T1>
template<class Alloc>
constexpr tuple(allocator_arg_t, const Alloc& a);
template<class Alloc>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const Types&...);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
template<class Alloc>
constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&);
template<class Alloc>
constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
Requires: Alloc shall satisfy the
Cpp17Allocator requirements (Table
34)
. For each
tuple assignment operator, an exception is thrown only if the
assignment of one of the types in
Types throws an exception
. In the function descriptions that follow, let
i be in the range
[0, sizeof...(Types))
in order,
Ti be the
ith type in
Types,
and
Ui be the
ith type in a
template parameter pack named
UTypes, where indexing is zero-based
. constexpr tuple& operator=(const tuple& u);
Effects: Assigns each element of
u to the corresponding
element of
*this. Remarks: This operator shall be defined as deleted unless
is_copy_assignable_v<Ti> is
true for all
i. constexpr tuple& operator=(tuple&& u) noexcept(see below);
Effects: For all
i, assigns
std::forward<Ti>(get<i>(u)) to
get<i>(*this). Remarks: This operator shall not participate in overload resolution unless
is_move_assignable_v<Ti> is
true for all
i. Remarks: The expression inside noexcept is equivalent to the logical and of the
following expressions:
is_nothrow_move_assignable_v<Ti>
where
Ti is the
ith type in
Types.template<class... UTypes> constexpr tuple& operator=(const tuple<UTypes...>& u);
Effects: Assigns each element of
u to the corresponding element
of
*this. Remarks: This operator shall not participate in overload resolution unless
sizeof...(Types) == sizeof...(UTypes) and
is_assignable_v<Ti&, const Ui&> is
true for all
i. template<class... UTypes> constexpr tuple& operator=(tuple<UTypes...>&& u);
Effects: For all
i, assigns
std::forward<Ui>(get<i>(u)) to
get<i>(*this). Remarks: This operator shall not participate in overload resolution unless
is_assignable_v<Ti&, Ui&&> == true for all
i and
sizeof...(Types) == sizeof...(UTypes). template<class U1, class U2> constexpr tuple& operator=(const pair<U1, U2>& u);
Effects: Assigns
u.first to the first element of
*this
and
u.second to the second element of
*this. Remarks: This operator shall not participate in overload resolution unless
sizeof...(Types) == 2 and
is_assignable_v<T0&, const U1&> is
true for the first type
T0 in
Types and
is_assignable_v<T1&, const U2&> is
true for the
second type
T1 in
Types. template<class U1, class U2> constexpr tuple& operator=(pair<U1, U2>&& u);
Effects: Assigns std::forward<U1>(u.first) to the first
element of *this and
std::forward<U2>(u.second) to the
second element of
*this. Remarks:
This operator shall not participate in overload resolution unless
sizeof...(Types) == 2 and
is_assignable_v<T0&, U1&&> is
true for the first type
T0 in
Types and
is_assignable_v<T1&, U2&&> is
true for the second
type
T1 in
Types. constexpr void swap(tuple& rhs) noexcept(see below);
Effects: Calls
swap for each element in
*this and its
corresponding element in
rhs. Remarks: The expression inside noexcept is equivalent to the logical
and of the following expressions:
is_nothrow_swappable_v<Ti>
where
Ti is the
ith type in
Types.Throws: Nothing unless one of the element-wise
swap calls throws an exception
. In the function descriptions that follow, the members of a template parameter pack
XTypes
are denoted by
Xi for
i in
[0, sizeof...(XTypes)) in
order, where indexing is zero-based
. template<class... TTypes>
constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&... t);
Returns: tuple<unwrap_ref_decay_t<TTypes>...>(std::forward<TTypes>(t)...). [
βExample:
int i; float j;
make_tuple(1, ref(i), cref(j))
creates a tuple of type
tuple<int, int&, const float&>. β
βend example β]
template<class... TTypes>
constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&... t) noexcept;
Effects: Constructs a tuple of references to the arguments in
t suitable
for forwarding as arguments to a function
. Because the result may contain references
to temporary variables, a program shall ensure that the return value of this
function does not outlive any of its arguments (e.g., the program should typically
not store the result in a named variable)
.Returns: tuple<TTypes&&...>(std::forward<TTypes>(t)...). template<class... TTypes>
constexpr tuple<TTypes&...> tie(TTypes&... t) noexcept;
Returns: tuple<TTypes&...>(t...). When an
argument in
t is
ignore, assigning
any value to the corresponding tuple element has no effect
.[
βExample: tie functions allow one to create tuples that unpack
tuples into variables
. ignore can be used for elements that
are not needed:
int i; std::string s;
tie(i, ignore, s) = make_tuple(42, 3.14, "C++");
β
βend example β]
template<class... Tuples>
constexpr tuple<CTypes...> tuple_cat(Tuples&&... tpls);
In the following paragraphs, let
Ti be the
ith type in
Tuples,
Ui be
remove_reference_t<Ti>, and
tpi be the
ith
parameter in the function parameter pack
tpls, where all indexing is
zero-based
.Requires: For all
i,
Ui shall be the type
cvi tuple<Argsi...>, where
cvi is the (possibly empty)
ith
cv-qualifier-seq and
Argsi is the template parameter pack representing the element
types in
Ui. Let
Aik be the
kth type in
Argsi. For all
Aik the following requirements shall be satisfied:
If Ti is deduced as an lvalue reference type, then
is_constructible_v<Aik, cviAik&> == true, otherwise
is_constructible_v<Aik, cviAik&&> == true.
Remarks: The types in
CTypes shall be equal to the ordered
sequence of the extended types
Args0..., Args1..., …, Argsnβ1...,
where
n is
equal to
sizeof...(Tuples). Let
ei... be the
ith
ordered sequence of tuple elements of the resulting
tuple object
corresponding to the type sequence
Argsi.Returns: A
tuple object constructed by initializing the
kith
type element
eik in
ei... with
get<ki>(std::forward<Ti>(tpi))
for each valid
ki and each group
ei in order
. [
βNote: An implementation may support additional types in the template parameter
pack
Tuples that support the
tuple-like protocol, such as
pair and
array. β
βend note β]
19.5.3.5 Calling a function with a tuple of arguments [tuple.apply]
template<class F, class Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t);
Effects:
Given the exposition-only function:
template<class F, class Tuple, size_t... I>
constexpr decltype(auto) apply-impl(F&& f, Tuple&& t, index_sequence<I...>) {
return INVOKE(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...);
}
Equivalent to:
return apply-impl(std::forward<F>(f), std::forward<Tuple>(t),
make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
template<class T, class Tuple>
constexpr T make_from_tuple(Tuple&& t);
Effects:
Given the exposition-only function:
template<class T, class Tuple, size_t... I>
constexpr T make-from-tuple-impl(Tuple&& t, index_sequence<I...>) {
return T(get<I>(std::forward<Tuple>(t))...);
}
Equivalent to:
return make-from-tuple-impl<T>(
forward<Tuple>(t),
make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
[
βNote: The type of
T must be supplied
as an explicit template parameter,
as it cannot be deduced from the argument list
. β
βend note β]
template<class T> struct tuple_size;
Remarks: All specializations of
tuple_size shall satisfy the
Cpp17UnaryTypeTrait requirements (
[meta.rqmts]) with a
base characteristic of
integral_constant<size_t, N>
for some
N. template<class... Types>
class tuple_size<tuple<Types...>> : public integral_constant<size_t, sizeof...(Types)> { };
template<size_t I, class... Types>
class tuple_element<I, tuple<Types...>> {
public:
using type = TI;
};
Requires: I < sizeof...(Types). The program is ill-formed if
I is out of bounds
.Type: TI is the
type of the
Ith element of
Types,
where indexing is zero-based
. template<class T> class tuple_size<const T>;
template<class T> class tuple_size<volatile T>;
template<class T> class tuple_size<const volatile T>;
Let
TS denote
tuple_size<T> of the
cv-unqualified type
T. If the expression
TS::value is well-formed
when treated as an unevaluated operand, then each
of the three templates shall satisfy the
Cpp17UnaryTypeTrait requirements (
[meta.rqmts])
with a base characteristic of
integral_constant<size_t, TS::value>
Otherwise, they shall have no member
value.Access checking is performed as if in a context
unrelated to
TS and
T. Only the validity of the immediate context of the expression is considered
. [
βNote: The compilation of the expression can result in side effects
such as the instantiation of class template specializations and
function template specializations, the generation of implicitly-defined functions, and so on
. Such side effects are not in the βimmediate contextβ and
can result in the program being ill-formed
. β
βend note β]
In addition to being available via inclusion of the
<tuple> header,
the three templates are available
when any of the headers
<array>,
<ranges>, or
<utility>
are included
.template<size_t I, class T> class tuple_element<I, const T>;
template<size_t I, class T> class tuple_element<I, volatile T>;
template<size_t I, class T> class tuple_element<I, const volatile T>;
Let
TE denote
tuple_element_t<I, T> of the
cv-unqualified type
T. Then
each of the three templates shall satisfy the
Cpp17TransformationTrait
requirements (
[meta.rqmts]) with a member typedef
type that names the following
type:
for the first specialization, add_const_t<TE>,
for the second specialization, add_volatile_t<TE>, and
for the third specialization,
add_cv_t<TE>.
In addition to being available via inclusion of the
<tuple> header,
the three templates are available
when any of the headers
<array>,
<ranges>, or
<utility>
are included
.template<size_t I, class... Types>
constexpr tuple_element_t<I, tuple<Types...>>&
get(tuple<Types...>& t) noexcept;
template<size_t I, class... Types>
constexpr tuple_element_t<I, tuple<Types...>>&&
get(tuple<Types...>&& t) noexcept;
template<size_t I, class... Types>
constexpr const tuple_element_t<I, tuple<Types...>>&
get(const tuple<Types...>& t) noexcept;
template<size_t I, class... Types>
constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
Requires: I < sizeof...(Types). The program is ill-formed if
I is out of bounds
.Returns: A reference to the
Ith element of
t, where
indexing is zero-based
. [
βNote A: If a type
T in
Types is some reference type
X&,
the return type is
X&, not
X&&. However, if the element type is a non-reference type
T,
the return type is
T&&. β
βend note β]
[
βNote B: If a type
T in
Types is some reference type
X&,
the return type is
X&, not
const X&. However, if the element type is a non-reference type
T,
the return type is
const T&. This is consistent with how constness is defined to work
for member variables of reference type
. β
βend note β]
template<class T, class... Types>
constexpr T& get(tuple<Types...>& t) noexcept;
template<class T, class... Types>
constexpr T&& get(tuple<Types...>&& t) noexcept;
template<class T, class... Types>
constexpr const T& get(const tuple<Types...>& t) noexcept;
template<class T, class... Types>
constexpr const T&& get(const tuple<Types...>&& t) noexcept;
Requires: The type
T occurs exactly once in
Types. Otherwise, the program is ill-formed
.Returns: A reference to the element of
t corresponding to the type
T in
Types. [
βExample:
const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6);
const int& i1 = get<int>(t);
const int& i2 = get<const int>(t);
const double& d = get<double>(t);
β
βend example β]
[
βNote: The reason
get is a
non-member function is that if this functionality had been
provided as a member function, code where the type
depended on a template parameter would have required using
the
template keyword
. β
βend note β]
template<class... TTypes, class... UTypes>
constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Requires: For all
i,
where
0 <= i and
i < sizeof...(TTypes),
get<i>(t) == get<i>(u) is a valid expression
returning a type that is convertible to
bool. sizeof...(TTypes) ==
sizeof...(UTypes). Returns: true if
get<i>(t) == get<i>(u) for all
i, otherwise
false. For any two zero-length tuples
e and
f,
e == f returns
true.Effects: The elementary comparisons are performed in order from the
zeroth index upwards
. No comparisons or element accesses are
performed after the first equality comparison that evaluates to
false.template<class... TTypes, class... UTypes>
constexpr bool operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
template<class... TTypes, class... UTypes>
constexpr bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Requires: For all
i,
where
0 <= i and
i < sizeof...(TTypes), both
get<i>(t) < get<i>(u)
and
get<i>(u) < get<i>(t)
are valid expressions returning types that are
convertible to
bool. sizeof...(TTypes) ==
sizeof...(UTypes). Returns: The result of a lexicographical comparison
between
t and
u. The result is defined
as:
(bool)(get<0>(t) < get<0>(u)) ||
(!(bool)(get<0>(u) < get<0>(t)) && ttail <
utail), where
rtail for some
tuple
r is a tuple containing all but the first element
of
r. For any two zero-length tuples
e
and
f,
e < f returns
false.template<class... TTypes, class... UTypes>
constexpr bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
template<class... TTypes, class... UTypes>
constexpr bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
template<class... TTypes, class... UTypes>
constexpr bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
[
βNote: The above definitions for comparison functions
do not require
ttail
(or
utail) to be constructed
. It may not
even be possible, as
t and
u are not required to be copy
constructible
. Also, all comparison functions are short circuited;
they do not perform element accesses beyond what is required to determine the
result of the comparison
. β
βend note β]
template<class... Types, class Alloc>
struct uses_allocator<tuple<Types...>, Alloc> : true_type { };
Requires: Alloc shall satisfy the
Cpp17Allocator
requirements (Table
34)
. [
βNote: Specialization of this trait informs other library components that
tuple can be constructed with an allocator, even though it does not have
a nested
allocator_type. β
βend note β]
template<class... Types>
constexpr void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
Remarks: This function shall not participate in overload resolution
unless
is_swappable_v<T> is
true
for every type
T in
Types. The expression inside noexcept is equivalent to:
noexcept(x.swap(y))
Effects: As if by
x.swap(y).