19 General utilities library [utilities]
namespace std {
template<class... Types>
class tuple {
public:
explicit(see below) constexpr tuple();
explicit(see below) constexpr tuple(const Types&...); template<class... UTypes>
explicit(see below) constexpr tuple(UTypes&&...);
tuple(const tuple&) = default;
tuple(tuple&&) = default;
template<class... UTypes>
explicit(see below) constexpr tuple(const tuple<UTypes...>&);
template<class... UTypes>
explicit(see below) constexpr tuple(tuple<UTypes...>&&);
template<class U1, class U2>
explicit(see below) constexpr tuple(const pair<U1, U2>&); template<class U1, class U2>
explicit(see below) constexpr tuple(pair<U1, U2>&&);
template<class Alloc>
tuple(allocator_arg_t, const Alloc& a);
template<class Alloc>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, const Types&...);
template<class Alloc, class... UTypes>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
template<class Alloc>
tuple(allocator_arg_t, const Alloc& a, const tuple&);
template<class Alloc>
tuple(allocator_arg_t, const Alloc& a, tuple&&);
template<class Alloc, class... UTypes>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
template<class Alloc, class... UTypes>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
template<class Alloc, class U1, class U2>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
template<class Alloc, class U1, class U2>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
tuple& operator=(const tuple&);
tuple& operator=(tuple&&) noexcept(see below);
template<class... UTypes>
tuple& operator=(const tuple<UTypes...>&);
template<class... UTypes>
tuple& operator=(tuple<UTypes...>&&);
template<class U1, class U2>
tuple& operator=(const pair<U1, U2>&); template<class U1, class U2>
tuple& operator=(pair<U1, U2>&&);
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
. explicit(see below) constexpr 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 β]
explicit(see below) constexpr 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> explicit(see below) constexpr 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> explicit(see below) constexpr 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> explicit(see below) constexpr 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> explicit(see below) constexpr 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> explicit(see below) constexpr 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>
tuple(allocator_arg_t, const Alloc& a);
template<class Alloc>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, const Types&...);
template<class Alloc, class... UTypes>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
template<class Alloc>
tuple(allocator_arg_t, const Alloc& a, const tuple&);
template<class Alloc>
tuple(allocator_arg_t, const Alloc& a, tuple&&);
template<class Alloc, class... UTypes>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
template<class Alloc, class... UTypes>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
template<class Alloc, class U1, class U2>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
template<class Alloc, class U1, class U2>
explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
Requires: Alloc shall satisfy the
Cpp17Allocator requirements (Table
33)
. 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
. 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. 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> 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> 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> 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> 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. 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<VTypes...> make_tuple(TTypes&&... t);
The pack
VTypes is defined as follows
. Let
Ui be
decay_t<Ti> for each
Ti in
TTypes. If
Ui is a specialization of
reference_wrapper, then
Vi in
VTypes is
Ui::type&,
otherwise
Vi is
Ui.Returns: tuple<VTypes...>(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 either of the headers
<array> 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 either of the headers
<array> 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: [Note A]
If a
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: [Note B]
Constness is shallow
. If a
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
33)
. [
β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>
void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
Remarks: This function shall not participate in overload resolution
unless
is_swappable_v<Ti> is
true
for all
i, where
0β€i<sizeof...(Types). The expression inside noexcept is equivalent to:
noexcept(x.swap(y))
Effects: As if by
x.swap(y).