namespace std { template <class... Types> class tuple { public: // [tuple.cnstr], tuple construction constexpr tuple(); explicit tuple(const Types&...); template <class... UTypes> explicit tuple(UTypes&&...); tuple(const tuple&) = default; tuple(tuple&&) = default; template <class... UTypes> tuple(const tuple<UTypes...>&); template <class... UTypes> tuple(tuple<UTypes...>&&); template <class U1, class U2> tuple(const pair<U1, U2>&); // iff sizeof...(Types) == 2 template <class U1, class U2> tuple(pair<U1, U2>&&); // iff sizeof...(Types) == 2 // allocator-extended constructors template <class Alloc> tuple(allocator_arg_t, const Alloc& a); template <class Alloc> tuple(allocator_arg_t, const Alloc& a, const Types&...); template <class Alloc, class... UTypes> 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> tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&); template <class Alloc, class... UTypes> tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&); template <class Alloc, class U1, class U2> tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); template <class Alloc, class U1, class U2> tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&); // [tuple.assign], tuple assignment 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>&); // iff sizeof...(Types) == 2 template <class U1, class U2> tuple& operator=(pair<U1, U2>&&); // iff sizeof...(Types) == 2 // [tuple.swap], tuple swap void swap(tuple&) noexcept(see below); }; }
For each tuple constructor, an exception is thrown only if the construction of one of the types in Types throws an exception.
In the constructor 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.
Requires: is_default_constructible<Ti>::value is true for all i.
Effects: Value initializes each element.
explicit tuple(const Types&...);
Requires: is_copy_constructible<Ti>::value is true for all i.
Effects: Initializes each element with the value of the corresponding parameter.
template <class... UTypes>
explicit tuple(UTypes&&... u);
Requires: sizeof...(Types) == sizeof...(UTypes). is_constructible<Ti, Ui&&>::value is true for all i.
Effects: Initializes the elements in the tuple with the corresponding value in std::forward<UTypes>(u).
Remark: This constructor shall not participate in overload resolution unless each type in UTypes is implicitly convertible to its corresponding type in Types.
tuple(const tuple& u) = default;
Requires: is_copy_constructible<Ti>::value is true for all i.
Effects: Initializes each element of *this with the corresponding element of u.
Requires: is_move_constructible<Ti>::value 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> tuple(const tuple<UTypes...>& u);
Requires: sizeof...(Types) == sizeof...(UTypes). is_constructible<Ti, const Ui&>::value is true for all i.
Effects: Constructs each element of *this with the corresponding element of u.
Remark: This constructor shall not participate in overload resolution unless const Ui& is implicitly convertible to Ti for all i.
template <class... UTypes> tuple(tuple<UTypes...>&& u);
Requires: sizeof...(Types) == sizeof...(UTypes). is_constructible<Ti, Ui&&>::value is true for all i.
Effects: For all i, initializes the ith element of *this with std::forward<Ui>(get<i>(u)).
Remark: This constructor shall not participate in overload resolution unless each type in UTypes is implicitly convertible to its corresponding type in Types.
template <class U1, class U2> tuple(const pair<U1, U2>& u);
Requires: sizeof...(Types) == 2. is_constructible<T0, const U1&>::value is true for the first type T0 in Types and is_constructible<T1, const U2&>::value is true for the second type T1 in Types.
Effects: Constructs the first element with u.first and the second element with u.second.
Remark: This constructor shall not participate in overload resolution unless const U1& is implicitly convertible to T0 and const U2& is implicitly convertible to T1.
template <class U1, class U2> tuple(pair<U1, U2>&& u);
Requires: sizeof...(Types) == 2. is_constructible<T0, U1&&>::value is true for the first type T0 in Types and is_constructible<T1, U2&&>::value is true for the second type T1 in Types.
Effects: Initializes the first element with std::forward<U1>(u.first) and the second element with std::forward<U2>(u.second).
Remark: This constructor shall not participate in overload resolution unless U1 is implicitly convertible to T0 and U2 is implicitly convertible to T1.
template <class Alloc>
tuple(allocator_arg_t, const Alloc& a);
template <class Alloc>
tuple(allocator_arg_t, const Alloc& a, const Types&...);
template <class Alloc, class... UTypes>
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>
tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
template <class Alloc, class... UTypes>
tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
template <class Alloc, class U1, class U2>
tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
template <class Alloc, class U1, class U2>
tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
Requires: Alloc shall meet the requirements for an Allocator ([allocator.requirements]).
Effects: Equivalent to the preceding constructors except that each element is constructed with uses-allocator construction ([allocator.uses.construction]).
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.
Requires: is_copy_assignable<Ti>::value is true for all i.
Effects: Assigns each element of u to the corresponding element of *this.
Returns: *this
tuple& operator=(tuple&& u) noexcept(see below);
Remark: The expression inside noexcept is equivalent to the logical and of the following expressions:
is_nothrow_move_assignable<Ti>::value
where Ti is the ith type in Types.
Requires: is_move_assignable<Ti>::value is true for all i.
Effects: For all i, assigns std::forward<Ti>(get<i>(u)) to get<i>(*this).
Returns: *this.
template <class... UTypes>
tuple& operator=(const tuple<UTypes...>& u);
Requires: sizeof...(Types) == sizeof...(UTypes) and is_assignable<Ti&, const Ui&>::value is true for all i.
Effects: Assigns each element of u to the corresponding element of *this.
Returns: *this
template <class... UTypes>
tuple& operator=(tuple<UTypes...>&& u);
Requires:
is_assignable<Ti&, Ui&&>::value == true for all i.
sizeof...(Types) ==
sizeof...(UTypes).
Effects: For all i, assigns std::forward<Ui>(get<i)>(u)) to get<i>(*this).
Returns: *this.
template <class U1, class U2> tuple& operator=(const pair<U1, U2>& u);
Requires: sizeof...(Types) == 2. is_assignable<T0&, const U1&>::value is true for the first type T0 in Types and is_assignable<T1&, const U2&>::value is true for the second type T1 in Types.
Effects: Assigns u.first to the first element of *this and u.second to the second element of *this.
Returns: *this
template <class U1, class U2> tuple& operator=(pair<U1, U2>&& u);
Requires: sizeof...(Types) == 2. is_assignable<T0&, U1&&>::value is true for the first type T0 in Types and is_assignable<T1&, U2&&>::value is true for the second type T1 in Types.
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.
Returns: *this.
void swap(tuple& rhs) noexcept(see below);
Remark: The expression inside noexcept is equivalent to the logical and of the following expressions:
noexcept(swap(declval<Ti&>>(), declval<Ti&>()))
where T1 is the ith type in Types.
Requires: Each element in *this shall be swappable with ([swappable.requirements]) the corresponding element in rhs.
Effects: Calls swap for each element in *this and its corresponding element in rhs.
Throws: Nothing unless one of the element-wise swap calls throws an exception.
In the function descriptions that follow, let i be in the range [0,sizeof...(TTypes)) in order and let Ti be the ith type in a template parameter pack named TTypes; let j be in the range [0,sizeof...(UTypes)) in order and Uj be the jth type in a template parameter pack named UTypes, where indexing is zero-based.
template<class... Types>
tuple<VTypes...> make_tuple(Types&&... t);
Let Ui be decay<Ti>::type for each Ti in Types. Then each Vi in VTypes is X& if Ui equals reference_wrapper<X>, otherwise Vi is Ui.
Returns: tuple<VTypes...>(std::forward<Types>(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... Types>
tuple<Types&&...> forward_as_tuple(Types&&... 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<Types&&...>(std::forward<Types>(t)...)
template<class... Types>
tuple<Types&...> tie(Types&... t) noexcept;
Returns: tuple<Types&>(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++");
// i == 42, s == "C++"
— end example ]
template <class... Tuples>
tuple<CTypes...> tuple_cat(Tuples&&... tpls);
In the following paragraphs, let Ti be the ith type in Tuples, Ui be remove_reference<Ti>::type, 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 parameter pack representing the element types in Ui. Let Aik be the kith type in Argsi. For all Aik the following requirements shall be satisfied: If Ti is deduced as an lvalue reference type, then is_constructible<Aik, cvi Aik&>::value == true, otherwise is_constructible<Aik, cvi Aik&&>::value == 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 parameter pack Tuples that support the tuple-like protocol, such as pair and array.
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:
typedef TI type;
};
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. Then each of the three templates shall meet the UnaryTypeTrait requirements ([meta.rqmts]) with a BaseCharacteristic of
integral_constant<remove_cv<decltype(TS::value)>::type, TS::value>
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<I, T> of the cv-unqualified type T. Then each of the three templates shall meet the TransformationTrait requirements ([meta.rqmts]) with a member typedef type that names the following type:
template <size_t I, class... Types>
typename tuple_element<I, tuple<Types...> >::type& get(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.
template <size_t I, class... types>
typename tuple_element<I, tuple<Types...> >::type&& get(tuple<Types...>&& t) noexcept;
Effects: Equivalent to
return std::forward<typename tuple_element<I, tuple<Types...> >
::type&&>(get<I>(t));
Note: 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&&.
template <size_t I, class... Types>
typename tuple_element<I, tuple<Types...> >::type const& get(const tuple<Types...>& t) noexcept;
Requires: I < sizeof...(Types). The program is ill-formed if I is out of bounds.
Returns: A const reference to the Ith element of t, where indexing is zero-based.
[ Note: 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 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 ]
[ Note: The reason get is a nonmember 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>
bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Requires: For all i, where 0 <= i and i < sizeof...(Types), get<i>(t) == get<i>(u) is a valid expression returning a type that is convertible to bool. sizeof...(TTypes) == sizeof...(UTypes).
Returns: true iff get<i>(t) == get<i>(u) for all i. 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>
bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Requires: For all i, where 0 <= i and i < sizeof...(Types), 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>
bool operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Returns: !(t == u).
template<class... TTypes, class... UTypes>
bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Returns: u < t.
template<class... TTypes, class... UTypes>
bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Returns: !(u < t)
template<class... TTypes, class... UTypes>
bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Returns: !(t < u)
[ Note: The above definitions for comparison operators 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 operators 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 be an Allocator ([allocator.requirements]).
[ 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);
Remark: The expression inside noexcept is equivalent to:
noexcept(x.swap(y))
Effects: x.swap(y)