[tuple] # 22 General utilities library [[utilities]](./#utilities) ## 22.4 Tuples [tuple] ### [22.4.1](#general) General [[tuple.general]](tuple.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1508) Subclause [tuple] describes the tuple library that provides a tuple type as the class template tuple that can be instantiated with any number of arguments[.](#general-1.sentence-1) Each template argument specifies the type of an element in the tuple[.](#general-1.sentence-2) Consequently, tuples are heterogeneous, fixed-size collections of values[.](#general-1.sentence-3) An instantiation of tuple with two arguments is similar to an instantiation of pair with the same two arguments[.](#general-1.sentence-4) See [[pairs]](pairs "22.3 Pairs")[.](#general-1.sentence-5) [2](#general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1518) In addition to being available via inclusion of the [](#header:%3ctuple%3e "22.4.2 Header synopsis [tuple.syn]") header,ignore ([[tuple.syn]](#syn "22.4.2 Header synopsis")) is available when[](utility.syn#header:%3cutility%3e "22.2.1 Header synopsis [utility.syn]") ([[utility]](utility "22.2 Utility components")) is included[.](#general-2.sentence-1) ### [22.4.2](#syn) Header synopsis [[tuple.syn]](tuple.syn) [🔗](#header:%3ctuple%3e) // all freestanding#include // see [[compare.syn]](compare.syn "17.12.1 Header synopsis")namespace std {// [[tuple.tuple]](#tuple "22.4.4 Class template tuple"), class template tupletemplateclass tuple; // [[tuple.like]](#like "22.4.3 Concept tuple-like"), concept [*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]")templateconcept [*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") = *see below*; // *exposition only*templateconcept [*pair-like*](#concept:pair-like "22.4.2 Header synopsis [tuple.syn]") = // *exposition only*[*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") && tuple_size_v> == 2; // [[tuple.common.ref]](#common.ref "22.4.10 common_­reference related specializations"), common_reference related specializationstemplate<[*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") TTuple, [*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") UTuple, template class TQual, template class UQual>struct basic_common_reference; template<[*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") TTuple, [*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") UTuple>struct common_type; // ignorestruct *ignore-type* { // *exposition only*constexpr const *ignore-type*&operator=(const auto &) const noexcept { return *this; }}; inline constexpr *ignore-type* ignore; // [[tuple.creation]](#creation "22.4.5 Tuple creation functions"), tuple creation functionstemplateconstexpr tuple...> make_tuple(TTypes&&...); templateconstexpr tuple forward_as_tuple(TTypes&&...) noexcept; templateconstexpr tuple tie(TTypes&...) noexcept; template<[*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]")... Tuples>constexpr tuple tuple_cat(Tuples&&...); // [[tuple.apply]](#apply "22.4.6 Calling a function with a tuple of arguments"), calling a function with a tuple of argumentstemplateconstexpr apply_result_t apply(F&& f, Tuple&& t)noexcept(is_nothrow_applicable_v); templateconstexpr T make_from_tuple(Tuple&& t); // [[tuple.helper]](#helper "22.4.7 Tuple helper classes"), tuple helper classestemplate struct tuple_size; // *not defined*template struct tuple_size; template struct tuple_size>; template struct tuple_element; // *not defined*template struct tuple_element; templatestruct tuple_element>; templateusing [tuple_element_t](#lib:tuple_element_t "22.4.2 Header synopsis [tuple.syn]") = typename tuple_element::type; // [[tuple.elem]](#elem "22.4.8 Element access"), element accesstemplateconstexpr tuple_element_t>& get(tuple&) noexcept; templateconstexpr tuple_element_t>&& get(tuple&&) noexcept; templateconstexpr const tuple_element_t>& get(const tuple&) noexcept; templateconstexpr const tuple_element_t>&& get(const tuple&&) noexcept; templateconstexpr T& get(tuple& t) noexcept; templateconstexpr T&& get(tuple&& t) noexcept; templateconstexpr const T& get(const tuple& t) noexcept; templateconstexpr const T&& get(const tuple&& t) noexcept; // [[tuple.rel]](#rel "22.4.9 Relational operators"), relational operatorstemplateconstexpr bool operator==(const tuple&, const tuple&); templateconstexpr bool operator==(const tuple&, const UTuple&); templateconstexpr common_comparison_category_t<*synth-three-way-result*...>operator<=>(const tuple&, const tuple&); templateconstexpr *see below* operator<=>(const tuple&, const UTuple&); // [[tuple.traits]](#traits "22.4.11 Tuple traits"), allocator-related traitstemplatestruct uses_allocator, Alloc>; // [[tuple.special]](#special "22.4.12 Tuple specialized algorithms"), specialized algorithmstemplateconstexpr void swap(tuple& x, tuple& y) noexcept(*see below*); templateconstexpr void swap(const tuple& x, const tuple& y) noexcept(*see below*); // [[tuple.helper]](#helper "22.4.7 Tuple helper classes"), tuple helper classestemplateconstexpr size_t [tuple_size_v](#lib:tuple_size_v "22.4.2 Header synopsis [tuple.syn]") = tuple_size::value;} ### [22.4.3](#like) Concept *tuple-like* [[tuple.like]](tuple.like) [🔗](#concept:tuple-like) `template concept [tuple-like](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") = see below; // exposition only ` [1](#like-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1645) A type T models and satisfies the exposition-only concept [*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") if remove_cvref_t is a specialization ofarray, complex, pair, tuple, or ranges​::​subrange[.](#like-1.sentence-1) ### [22.4.4](#tuple) Class template tuple [[tuple.tuple]](tuple.tuple) #### [22.4.4.1](#tuple.general) General [[tuple.tuple.general]](tuple.tuple.general) [🔗](#lib:tuple_) namespace std {templateclass tuple {public:// [[tuple.cnstr]](#cnstr "22.4.4.2 Construction"), tuple constructionconstexpr explicit(*see below*) tuple(); constexpr explicit(*see below*) tuple(const Types&...); // only if sizeof...(Types) >= 1templateconstexpr explicit(*see below*) tuple(UTypes&&...); // only if sizeof...(Types) >= 1 tuple(const tuple&) = default; tuple(tuple&&) = default; templateconstexpr explicit(*see below*) tuple(tuple&); templateconstexpr explicit(*see below*) tuple(const tuple&); templateconstexpr explicit(*see below*) tuple(tuple&&); templateconstexpr explicit(*see below*) tuple(const tuple&&); templateconstexpr explicit(*see below*) tuple(pair&); // only if sizeof...(Types) == 2templateconstexpr explicit(*see below*) tuple(const pair&); // only if sizeof...(Types) == 2templateconstexpr explicit(*see below*) tuple(pair&&); // only if sizeof...(Types) == 2templateconstexpr explicit(*see below*) tuple(const pair&&); // only if sizeof...(Types) == 2template<[*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") UTuple>constexpr explicit(*see below*) tuple(UTuple&&); // allocator-extended constructorstemplateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a); templateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a, const Types&...); templateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a, UTypes&&...); templateconstexpr tuple(allocator_arg_t, const Alloc& a, const tuple&); templateconstexpr tuple(allocator_arg_t, const Alloc& a, tuple&&); templateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a, tuple&); templateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a, const tuple&); templateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a, tuple&&); templateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a, const tuple&&); templateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a, pair&); templateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a, const pair&); templateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a, pair&&); templateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a, const pair&&); templateconstexpr explicit(*see below*) tuple(allocator_arg_t, const Alloc& a, UTuple&&); // [[tuple.assign]](#assign "22.4.4.3 Assignment"), tuple assignmentconstexpr tuple& operator=(const tuple&); constexpr const tuple& operator=(const tuple&) const; constexpr tuple& operator=(tuple&&) noexcept(*see below*); constexpr const tuple& operator=(tuple&&) const; templateconstexpr tuple& operator=(const tuple&); templateconstexpr const tuple& operator=(const tuple&) const; templateconstexpr tuple& operator=(tuple&&); templateconstexpr const tuple& operator=(tuple&&) const; templateconstexpr tuple& operator=(const pair&); // only if sizeof...(Types) == 2templateconstexpr const tuple& operator=(const pair&) const; // only if sizeof...(Types) == 2templateconstexpr tuple& operator=(pair&&); // only if sizeof...(Types) == 2templateconstexpr const tuple& operator=(pair&&) const; // only if sizeof...(Types) == 2template<[*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") UTuple>constexpr tuple& operator=(UTuple&&); template<[*tuple-like*](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") UTuple>constexpr const tuple& operator=(UTuple&&) const; // [[tuple.swap]](#swap "22.4.4.4 swap"), tuple swapconstexpr void swap(tuple&) noexcept(*see below*); constexpr void swap(const tuple&) const noexcept(*see below*); }; template tuple(UTypes...) -> tuple; template tuple(pair) -> tuple; template tuple(allocator_arg_t, Alloc, UTypes...) -> tuple; template tuple(allocator_arg_t, Alloc, pair) -> tuple; template tuple(allocator_arg_t, Alloc, tuple) -> tuple;} [1](#tuple.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1782) If a program declares an explicit or partial specialization of tuple, the program is ill-formed, no diagnostic required[.](#tuple.general-1.sentence-1) #### [22.4.4.2](#cnstr) Construction [[tuple.cnstr]](tuple.cnstr) [1](#cnstr-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1788) In the descriptions that follow, let i be in the range [0, sizeof...(Types)) in order, Ti be the ith type in Types, andUi be the ith type in a template parameter pack named UTypes, where indexing is zero-based[.](#cnstr-1.sentence-1) [2](#cnstr-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1795) For each tuple constructor, an exception is thrown only if the construction of one of the types in Types throws an exception[.](#cnstr-2.sentence-1) [3](#cnstr-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1799) The defaulted move and copy constructor, respectively, oftuple is a constexpr function if and only if all required element-wise initializations for move and copy, respectively, would be constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers"))[.](#cnstr-3.sentence-1) The defaulted move and copy constructor of tuple<> are constexpr functions[.](#cnstr-3.sentence-2) [4](#cnstr-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1807) If is_trivially_destructible_v is true for all Ti, then the destructor of tuple is trivial[.](#cnstr-4.sentence-1) [5](#cnstr-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1811) The default constructor of tuple<> is trivial[.](#cnstr-5.sentence-1) [🔗](#lib:tuple,constructor) `constexpr explicit(see below) tuple(); ` [6](#cnstr-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1820) *Constraints*: is_default_constructible_v is true for all i[.](#cnstr-6.sentence-1) [7](#cnstr-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1824) *Effects*: Value-initializes each element[.](#cnstr-7.sentence-1) [8](#cnstr-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1828) *Remarks*: The expression inside explicit evaluates to true if and only if Ti is not copy-list-initializable from an empty list for at least one i[.](#cnstr-8.sentence-1) [*Note [1](#cnstr-note-1)*: This behavior can be implemented with a trait that checks whether a const Ti& can be initialized with {}[.](#cnstr-8.sentence-2) — *end note*] [🔗](#lib:tuple,constructor_) `constexpr explicit(see below) tuple(const Types&...); ` [9](#cnstr-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1846) *Constraints*: sizeof...(Types) ≥ 1 andis_copy_constructible_v is true for all i[.](#cnstr-9.sentence-1) [10](#cnstr-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1851) *Effects*: Initializes each element with the value of the corresponding parameter[.](#cnstr-10.sentence-1) [11](#cnstr-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1856) *Remarks*: The expression inside explicit is equivalent to:!conjunction_v...> [🔗](#lib:tuple,constructor__) `template constexpr explicit(see below) tuple(UTypes&&... u); ` [12](#cnstr-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1870) Let *disambiguating-constraint* be: - [(12.1)](#cnstr-12.1) negation, tuple>> if sizeof...(Types) is 1; - [(12.2)](#cnstr-12.2) otherwise,bool_constant, allocator_arg_t> || is_- same_v, allocator_arg_t>> if sizeof...(Types) is 2 or 3; - [(12.3)](#cnstr-12.3) otherwise, true_type[.](#cnstr-12.sentence-1) [13](#cnstr-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1885) *Constraints*: - [(13.1)](#cnstr-13.1) sizeof...(Types) equals sizeof...(UTypes), - [(13.2)](#cnstr-13.2) sizeof...(Types) ≥ 1, and - [(13.3)](#cnstr-13.3) conjunction_v<*disambiguating-constraint*, is_constructible...> is true[.](#cnstr-13.sentence-1) [14](#cnstr-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1897) *Effects*: Initializes the elements in the tuple with the corresponding value in std​::​forward(u)[.](#cnstr-14.sentence-1) [15](#cnstr-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1902) *Remarks*: The expression inside explicit is equivalent to:!conjunction_v...> This constructor is defined as deleted if(reference_constructs_from_temporary_v || ...) is true[.](#cnstr-15.sentence-2) [🔗](#lib:tuple,constructor___) `tuple(const tuple& u) = default; ` [16](#cnstr-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1921) *Mandates*: is_copy_constructible_v is true for all i[.](#cnstr-16.sentence-1) [17](#cnstr-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1925) *Effects*: Initializes each element of *this with the corresponding element of u[.](#cnstr-17.sentence-1) [🔗](#lib:tuple,constructor____) `tuple(tuple&& u) = default; ` [18](#cnstr-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1937) *Constraints*: is_move_constructible_v is true for all i[.](#cnstr-18.sentence-1) [19](#cnstr-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1941) *Effects*: For all i, initializes the ith element of *this withstd​::​forward(get(u))[.](#cnstr-19.sentence-1) [🔗](#lib:tuple,constructor_____) `template constexpr explicit(see below) tuple(tuple& u); template constexpr explicit(see below) tuple(const tuple& u); template constexpr explicit(see below) tuple(tuple&& u); template constexpr explicit(see below) tuple(const tuple&& u); ` [20](#cnstr-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1956) Let I be the pack 0, 1, …, (sizeof...(Types) - 1)[.](#cnstr-20.sentence-1) Let *FWD*(u) be static_cast(u)[.](#cnstr-20.sentence-2) [21](#cnstr-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1960) *Constraints*: - [(21.1)](#cnstr-21.1) sizeof...(Types) equals sizeof...(UTypes), and - [(21.2)](#cnstr-21.2) (is_constructible_v(*FWD*(u)))> && ...) is true, and - [(21.3)](#cnstr-21.3) either sizeof...(Types) is not 1, or (when Types... expands to T andUTypes... expands to U)is_convertible_v,is_constructible_v, andis_same_v are all false[.](#cnstr-21.sentence-1) [22](#cnstr-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1977) *Effects*: For all i, initializes the ith element of *this with get(*FWD*(u))[.](#cnstr-22.sentence-1) [23](#cnstr-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1982) *Remarks*: The expression inside explicit is equivalent to:!(is_convertible_v(*FWD*(u))), Types> && ...) The constructor is defined as deleted if(reference_constructs_from_temporary_v(*FWD*(u)))> || ...) is true[.](#cnstr-23.sentence-2) [🔗](#lib:tuple,constructor______) `template constexpr explicit(see below) tuple(pair& u); template constexpr explicit(see below) tuple(const pair& u); template constexpr explicit(see below) tuple(pair&& u); template constexpr explicit(see below) tuple(const pair&& u); ` [24](#cnstr-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2004) Let *FWD*(u) be static_cast(u)[.](#cnstr-24.sentence-1) [25](#cnstr-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2007) *Constraints*: - [(25.1)](#cnstr-25.1) sizeof...(Types) is 2, - [(25.2)](#cnstr-25.2) is_constructible_v(*FWD*(u)))> is true, and - [(25.3)](#cnstr-25.3) is_constructible_v(*FWD*(u)))> is true[.](#cnstr-25.sentence-1) [26](#cnstr-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2018) *Effects*: Initializes the first element with get<0>(*FWD*(u)) and the second element with get<1>(*FWD*(​u))[.](#cnstr-26.sentence-1) [27](#cnstr-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2023) *Remarks*: The expression inside explicit is equivalent to:!is_convertible_v(*FWD*(u))), T0> ||!is_convertible_v(*FWD*(u))), T1> The constructor is defined as deleted ifreference_constructs_from_temporary_v(*FWD*(u)))> || reference_constructs_from_temporary_v(*FWD*(u)))> is true[.](#cnstr-27.sentence-2) [🔗](#lib:tuple,constructor_______) `template<[tuple-like](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") UTuple> constexpr explicit(see below) tuple(UTuple&& u); ` [28](#cnstr-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2045) Let I be the pack 0, 1, …, (sizeof...(Types) - 1)[.](#cnstr-28.sentence-1) [29](#cnstr-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2048) *Constraints*: - [(29.1)](#cnstr-29.1) [*different-from*](range.utility.helpers#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]") ([[range.utility.helpers]](range.utility.helpers "25.5.2 Helper concepts")) is true, - [(29.2)](#cnstr-29.2) remove_cvref_t is not a specialization of ranges​::​subrange, - [(29.3)](#cnstr-29.3) sizeof...(Types) equals tuple_size_v>, - [(29.4)](#cnstr-29.4) (is_constructible_v(std​::​forward(u)))> && ...) istrue, and - [(29.5)](#cnstr-29.5) either sizeof...(Types) is not 1, or (when Types... expands to T)is_convertible_v andis_constructible_v are both false[.](#cnstr-29.sentence-1) [30](#cnstr-30) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2075) *Effects*: For all i, initializes the ith element of *this withget(std​::​forward(u))[.](#cnstr-30.sentence-1) [31](#cnstr-31) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2080) *Remarks*: The expression inside explicit is equivalent to:!(is_convertible_v(std::forward(u))), Types> && ...) The constructor is defined as deleted if(reference_constructs_from_temporary_v(std::forward(u)))>|| ...) is true[.](#cnstr-31.sentence-2) [🔗](#lib:tuple,constructor________) `template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a); template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const Types&...); template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTypes&&...); template constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&); template constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&); template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple&); template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple&); template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple&&); template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple&&); template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair&); template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair&); template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair&&); template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair&&); template constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTuple&&); ` [32](#cnstr-32) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2139) *Preconditions*: Alloc meets the [*Cpp17Allocator*](allocator.requirements.general#:Cpp17Allocator "16.4.4.6.1 General [allocator.requirements.general]") requirements ([[allocator.requirements.general]](allocator.requirements.general "16.4.4.6.1 General"))[.](#cnstr-32.sentence-1) [33](#cnstr-33) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2144) *Effects*: Equivalent to the preceding constructors except that each element is constructed with[uses-allocator construction](allocator.uses.construction#def:uses-allocator_construction "20.2.8.2 Uses-allocator construction [allocator.uses.construction]")[.](#cnstr-33.sentence-1) #### [22.4.4.3](#assign) Assignment [[tuple.assign]](tuple.assign) [1](#assign-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2152) For each tuple assignment operator, an exception is thrown only if the assignment of one of the types in Types throws an exception[.](#assign-1.sentence-1) 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[.](#assign-1.sentence-2) [🔗](#lib:operator=,tuple) `constexpr tuple& operator=(const tuple& u); ` [2](#assign-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2166) *Effects*: Assigns each element of u to the corresponding element of *this[.](#assign-2.sentence-1) [3](#assign-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2171) *Returns*: *this[.](#assign-3.sentence-1) [4](#assign-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2175) *Remarks*: This operator is defined as deleted unlessis_copy_assignable_v is true for all i[.](#assign-4.sentence-1) [🔗](#lib:operator=,tuple_) `constexpr const tuple& operator=(const tuple& u) const; ` [5](#assign-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2187) *Constraints*: (is_copy_assignable_v && ...) is true[.](#assign-5.sentence-1) [6](#assign-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2191) *Effects*: Assigns each element of u to the corresponding element of *this[.](#assign-6.sentence-1) [7](#assign-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2195) *Returns*: *this[.](#assign-7.sentence-1) [🔗](#lib:operator=,tuple__) `constexpr tuple& operator=(tuple&& u) noexcept(see below); ` [8](#assign-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2206) *Constraints*: is_move_assignable_v is true for all i[.](#assign-8.sentence-1) [9](#assign-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2210) *Effects*: For all i, assigns std​::​forward(get(u)) toget(*this)[.](#assign-9.sentence-1) [10](#assign-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2215) *Returns*: *this[.](#assign-10.sentence-1) [11](#assign-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2219) *Remarks*: The exception specification is equivalent to the logical and of the following expressions:is_nothrow_move_assignable_v where Ti is the ith type in Types[.](#assign-11.sentence-1) [🔗](#lib:operator=,tuple___) `constexpr const tuple& operator=(tuple&& u) const; ` [12](#assign-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2235) *Constraints*: (is_assignable_v && ...) is true[.](#assign-12.sentence-1) [13](#assign-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2239) *Effects*: For all i, assigns std​::​forward(get(u)) to get(*this)[.](#assign-13.sentence-1) [14](#assign-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2244) *Returns*: *this[.](#assign-14.sentence-1) [🔗](#lib:operator=,tuple____) `template constexpr tuple& operator=(const tuple& u); ` [15](#assign-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2255) *Constraints*: - [(15.1)](#assign-15.1) sizeof...(Types) equals sizeof...(UTypes) and - [(15.2)](#assign-15.2) is_assignable_v is true for all i[.](#assign-15.sentence-1) [16](#assign-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2262) *Effects*: Assigns each element of u to the corresponding element of *this[.](#assign-16.sentence-1) [17](#assign-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2267) *Returns*: *this[.](#assign-17.sentence-1) [🔗](#lib:operator=,tuple_____) `template constexpr const tuple& operator=(const tuple& u) const; ` [18](#assign-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2278) *Constraints*: - [(18.1)](#assign-18.1) sizeof...(Types) equals sizeof...(UTypes) and - [(18.2)](#assign-18.2) (is_assignable_v && ...) is true[.](#assign-18.sentence-1) [19](#assign-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2287) *Effects*: Assigns each element of u to the corresponding element of *this[.](#assign-19.sentence-1) [20](#assign-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2291) *Returns*: *this[.](#assign-20.sentence-1) [🔗](#lib:operator=,tuple______) `template constexpr tuple& operator=(tuple&& u); ` [21](#assign-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2302) *Constraints*: - [(21.1)](#assign-21.1) sizeof...(Types) equals sizeof...(UTypes) and - [(21.2)](#assign-21.2) is_assignable_v is true for all i[.](#assign-21.sentence-1) [22](#assign-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2309) *Effects*: For all i, assigns std​::​forward(get(u)) toget(*this)[.](#assign-22.sentence-1) [23](#assign-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2314) *Returns*: *this[.](#assign-23.sentence-1) [🔗](#lib:operator=,tuple_______) `template constexpr const tuple& operator=(tuple&& u) const; ` [24](#assign-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2325) *Constraints*: - [(24.1)](#assign-24.1) sizeof...(Types) equals sizeof...(UTypes) and - [(24.2)](#assign-24.2) (is_assignable_v && ...) is true[.](#assign-24.sentence-1) [25](#assign-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2334) *Effects*: For all i, assigns std​::​forward(get(u)) to get(*this)[.](#assign-25.sentence-1) [26](#assign-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2339) *Returns*: *this[.](#assign-26.sentence-1) [🔗](#lib:operator=,tuple________) `template constexpr tuple& operator=(const pair& u); ` [27](#assign-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2351) *Constraints*: - [(27.1)](#assign-27.1) sizeof...(Types) is 2 and - [(27.2)](#assign-27.2) is_assignable_v is true, and - [(27.3)](#assign-27.3) is_assignable_v is true[.](#assign-27.sentence-1) [28](#assign-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2359) *Effects*: Assigns u.first to the first element of *this and u.second to the second element of *this[.](#assign-28.sentence-1) [29](#assign-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2364) *Returns*: *this[.](#assign-29.sentence-1) [🔗](#lib:operator=,tuple_________) `template constexpr const tuple& operator=(const pair& u) const; ` [30](#assign-30) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2375) *Constraints*: - [(30.1)](#assign-30.1) sizeof...(Types) is 2, - [(30.2)](#assign-30.2) is_assignable_v is true, and - [(30.3)](#assign-30.3) is_assignable_v is true[.](#assign-30.sentence-1) [31](#assign-31) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2386) *Effects*: Assigns u.first to the first element andu.second to the second element[.](#assign-31.sentence-1) [32](#assign-32) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2391) *Returns*: *this[.](#assign-32.sentence-1) [🔗](#lib:operator=,tuple__________) `template constexpr tuple& operator=(pair&& u); ` [33](#assign-33) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2403) *Constraints*: - [(33.1)](#assign-33.1) sizeof...(Types) is 2 and - [(33.2)](#assign-33.2) is_assignable_v is true, and - [(33.3)](#assign-33.3) is_assignable_v is true[.](#assign-33.sentence-1) [34](#assign-34) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2411) *Effects*: Assigns std​::​forward(u.first) to the first element of *this and std​::​forward(u.second) to the second element of *this[.](#assign-34.sentence-2) [35](#assign-35) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2417) *Returns*: *this[.](#assign-35.sentence-1) [🔗](#lib:operator=,tuple___________) `template constexpr const tuple& operator=(pair&& u) const; ` [36](#assign-36) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2428) *Constraints*: - [(36.1)](#assign-36.1) sizeof...(Types) is 2, - [(36.2)](#assign-36.2) is_assignable_v is true, and - [(36.3)](#assign-36.3) is_assignable_v is true[.](#assign-36.sentence-1) [37](#assign-37) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2439) *Effects*: Assigns std​::​forward(u.first) to the first element and std​::​forward(u.second) to the second element[.](#assign-37.sentence-2) [38](#assign-38) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2444) *Returns*: *this[.](#assign-38.sentence-1) [🔗](#lib:operator=,tuple____________) `template<[tuple-like](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") UTuple> constexpr tuple& operator=(UTuple&& u); ` [39](#assign-39) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2456) *Constraints*: - [(39.1)](#assign-39.1) [*different-from*](range.utility.helpers#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]") ([[range.utility.helpers]](range.utility.helpers "25.5.2 Helper concepts")) is true, - [(39.2)](#assign-39.2) remove_cvref_t is not a specialization of ranges​::​subrange, - [(39.3)](#assign-39.3) sizeof...(Types) equals tuple_size_v>, and - [(39.4)](#assign-39.4) is_assignable_v(std​::​forward(u)))> is true for all i[.](#assign-39.sentence-1) [40](#assign-40) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2476) *Effects*: For all i, assigns get(std​::​forward(u)) to get(*this)[.](#assign-40.sentence-1) [41](#assign-41) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2481) *Returns*: *this[.](#assign-41.sentence-1) [🔗](#lib:operator=,tuple_____________) `template<[tuple-like](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") UTuple> constexpr const tuple& operator=(UTuple&& u) const; ` [42](#assign-42) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2493) *Constraints*: - [(42.1)](#assign-42.1) [*different-from*](range.utility.helpers#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]") ([[range.utility.helpers]](range.utility.helpers "25.5.2 Helper concepts")) is true, - [(42.2)](#assign-42.2) remove_cvref_t is not a specialization of ranges​::​subrange, - [(42.3)](#assign-42.3) sizeof...(Types) equals tuple_size_v>, and - [(42.4)](#assign-42.4) is_assignable_v(std​::​forward(u)))> is true for all i[.](#assign-42.sentence-1) [43](#assign-43) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2513) *Effects*: For all i, assignsget(std​::​forward(u)) to get(*this)[.](#assign-43.sentence-1) [44](#assign-44) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2518) *Returns*: *this[.](#assign-44.sentence-1) #### [22.4.4.4](#swap) swap [[tuple.swap]](tuple.swap) [🔗](#lib:swap,tuple) `constexpr void swap(tuple& rhs) noexcept(see below); constexpr void swap(const tuple& rhs) const noexcept(see below); ` [1](#swap-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2532) Let i be in the range [0, sizeof...(Types)) in order[.](#swap-1.sentence-1) [2](#swap-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2535) *Mandates*: - [(2.1)](#swap-2.1) For the first overload,(is_swappable_v && ...) is true[.](#swap-2.1.sentence-1) - [(2.2)](#swap-2.2) For the second overload,(is_swappable_v && ...) is true[.](#swap-2.2.sentence-1) [3](#swap-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2546) *Preconditions*: For all i, get(*this) is swappable with ([[swappable.requirements]](swappable.requirements "16.4.4.3 Swappable requirements")) get(rhs)[.](#swap-3.sentence-1) [4](#swap-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2550) *Effects*: For each i, calls swap for get(*this) and get(rhs)[.](#swap-4.sentence-1) [5](#swap-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2554) *Throws*: Nothing unless one of the element-wise swap calls throws an exception[.](#swap-5.sentence-1) [6](#swap-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2558) *Remarks*: The exception specification is equivalent to - [(6.1)](#swap-6.1) (is_nothrow_swappable_v && ...) for the first overload and - [(6.2)](#swap-6.2) (is_nothrow_swappable_v && ...) for the second overload[.](#swap-6.sentence-1) ### [22.4.5](#creation) Tuple creation functions [[tuple.creation]](tuple.creation) [🔗](#lib:make_tuple) `template constexpr tuple...> make_tuple(TTypes&&... t); ` [1](#creation-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2579) *Returns*: tuple...>(std​::​forward(t)...)[.](#creation-1.sentence-1) [2](#creation-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2583) [*Example [1](#creation-example-1)*: int i; float j; make_tuple(1, ref(i), cref(j)); creates a tuple of type tuple[.](#creation-2.sentence-1) — *end example*] [🔗](#lib:forward_as_tuple) `template constexpr tuple forward_as_tuple(TTypes&&... t) noexcept; ` [3](#creation-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2601) *Effects*: Constructs a tuple of references to the arguments in t suitable for forwarding as arguments to a function[.](#creation-3.sentence-1) Because the result may contain references to temporary objects, 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)[.](#creation-3.sentence-2) [4](#creation-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2609) *Returns*: tuple(std​::​forward(t)...)[.](#creation-4.sentence-1) [🔗](#lib:tie) `template constexpr tuple tie(TTypes&... t) noexcept; ` [5](#creation-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2623) *Returns*: tuple(t...)[.](#creation-5.sentence-1) [6](#creation-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2627) [*Example [2](#creation-example-2)*: tie functions allow one to create tuples that unpack tuples into variables[.](#creation-6.sentence-1) 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*] [🔗](#lib:tuple_cat) `template<[tuple-like](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]")... Tuples> constexpr tuple tuple_cat(Tuples&&... tpls); ` [7](#creation-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2647) Let n be sizeof...(Tuples)[.](#creation-7.sentence-1) For every integer 0≤i[.](#creation-7.2.sentence-1) - [(7.3)](#creation-7.3) Let tpi be the ith element in the function parameter pack tpls[.](#creation-7.3.sentence-1) - [(7.4)](#creation-7.4) Let Si be tuple_size_v[.](#creation-7.4.sentence-1) - [(7.5)](#creation-7.5) Let Eki be tuple_element_t[.](#creation-7.5.sentence-1) - [(7.6)](#creation-7.6) Let eki be get(std​::​forward(tpi))[.](#creation-7.6.sentence-1) - [(7.7)](#creation-7.7) Let Elemsi be a pack of the types E0i,…,ESi−1i[.](#creation-7.7.sentence-1) - [(7.8)](#creation-7.8) Let elemsi be a pack of the expressions e0i,…,eSi−1i[.](#creation-7.8.sentence-1) The types in CTypes are equal to the ordered sequence of the expanded packs of typesElems0..., Elems1..., …, Elemsn−1...[.](#creation-7.sentence-3) Let celems be the ordered sequence of the expanded packs of expressionselems0..., …, elemsn−1...[.](#creation-7.sentence-4) [8](#creation-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2676) *Mandates*: (is_constructible_v && ...) is true[.](#creation-8.sentence-1) [9](#creation-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2680) *Returns*: tuple(celems...)[.](#creation-9.sentence-1) ### [22.4.6](#apply) Calling a function with a tuple of arguments [[tuple.apply]](tuple.apply) [🔗](#lib:apply) `template constexpr apply_result_t apply(F&& f, Tuple&& t) noexcept(is_nothrow_applicable_v); ` [1](#apply-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2695) *Effects*: Given the exposition-only function template:namespace std {templateconstexpr decltype(auto) *apply-impl*(F&& f, Tuple&& t, index_sequence) {// *exposition only*return *INVOKE*(std::forward(f), get(std::forward(t))...); // see [[func.require]](func.require "22.10.4 Requirements")}} Equivalent to:return *apply-impl*(std::forward(f), std::forward(t), make_index_sequence>>{}); [🔗](#lib:make_from_tuple) `template constexpr T make_from_tuple(Tuple&& t); ` [2](#apply-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2721) *Mandates*: If tuple_size_v> is 1, thenreference_constructs_from_temporary_v(declval()))> is false[.](#apply-2.sentence-1) [3](#apply-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2728) *Effects*: Given the exposition-only function template:namespace std {templaterequires is_constructible_v(declval()))...>constexpr T *make-from-tuple-impl*(Tuple&& t, index_sequence) { // *exposition only*return T(get(std::forward(t))...); }} Equivalent to:return *make-from-tuple-impl*( std::forward(t), make_index_sequence>>{}); [*Note [1](#apply-note-1)*: The type of T must be supplied as an explicit template parameter, as it cannot be deduced from the argument list[.](#apply-3.sentence-2) — *end note*] ### [22.4.7](#helper) Tuple helper classes [[tuple.helper]](tuple.helper) [🔗](#lib:tuple_size,in_general) `template struct tuple_size; ` [1](#helper-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2761) Except where specified otherwise, all specializations of tuple_size meet the[*Cpp17UnaryTypeTrait*](meta.rqmts#:Cpp17UnaryTypeTrait "21.3.2 Requirements [meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2 Requirements")) with a base characteristic of integral_constant for some N[.](#helper-1.sentence-1) [🔗](#lib:tuple_size) `template struct tuple_size> : integral_constant { }; ` [🔗](#lib:tuple_element) `template struct tuple_element> { using type = TI; }; ` [2](#helper-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2784) *Mandates*: I < sizeof...(Types)[.](#helper-2.sentence-1) [3](#helper-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2788) *Type*: TI is the type of the Ith element of Types, where indexing is zero-based[.](#helper-3.sentence-1) [🔗](#lib:tuple_size_) `template struct tuple_size; ` [4](#helper-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2801) Let TS denote tuple_size of the cv-unqualified type T[.](#helper-4.sentence-1) If the expression TS​::​value is well-formed when treated as an [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3 Context dependence [expr.context]"), then each specialization of the template meets the [*Cpp17UnaryTypeTrait*](meta.rqmts#:Cpp17UnaryTypeTrait "21.3.2 Requirements [meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2 Requirements")) with a base characteristic ofintegral_constant Otherwise, it has no member value[.](#helper-4.sentence-3) [5](#helper-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2812) Access checking is performed as if in a context unrelated to TS and T[.](#helper-5.sentence-1) Only the validity of the immediate context of the expression is considered[.](#helper-5.sentence-2) [*Note [1](#helper-note-1)*: 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[.](#helper-5.sentence-3) Such side effects are not in the “immediate context” and can result in the program being ill-formed[.](#helper-5.sentence-4) — *end note*] [6](#helper-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2824) In addition to being available via inclusion of the [](#header:%3ctuple%3e "22.4.2 Header synopsis [tuple.syn]") header, the template is available when any of the headers[](array.syn#header:%3carray%3e "23.3.2 Header synopsis [array.syn]"),[](ranges.syn#header:%3cranges%3e "25.2 Header synopsis [ranges.syn]"), or[](utility.syn#header:%3cutility%3e "22.2.1 Header synopsis [utility.syn]") are included[.](#helper-6.sentence-1) [🔗](#lib:tuple_element_) `template struct tuple_element; ` [7](#helper-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2840) Let TE denote tuple_element_t of the cv-unqualified type T[.](#helper-7.sentence-1) Then each specialization of the template meets the [*Cpp17TransformationTrait*](meta.rqmts#:Cpp17TransformationTrait "21.3.2 Requirements [meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2 Requirements")) with a member typedef type that names the type add_const_t[.](#helper-7.sentence-2) [8](#helper-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2845) In addition to being available via inclusion of the [](#header:%3ctuple%3e "22.4.2 Header synopsis [tuple.syn]") header, the template is available when any of the headers[](array.syn#header:%3carray%3e "23.3.2 Header synopsis [array.syn]"),[](ranges.syn#header:%3cranges%3e "25.2 Header synopsis [ranges.syn]"), or[](utility.syn#header:%3cutility%3e "22.2.1 Header synopsis [utility.syn]") are included[.](#helper-8.sentence-1) ### [22.4.8](#elem) Element access [[tuple.elem]](tuple.elem) [🔗](#lib:get,tuple) `template constexpr tuple_element_t>& get(tuple& t) noexcept; template constexpr tuple_element_t>&& get(tuple&& t) noexcept; // #1 template constexpr const tuple_element_t>& get(const tuple& t) noexcept; // #2 template constexpr const tuple_element_t>&& get(const tuple&& t) noexcept; ` [1](#elem-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2873) *Mandates*: I < sizeof...(Types)[.](#elem-1.sentence-1) [2](#elem-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2877) *Returns*: A reference to the Ith element of t, where indexing is zero-based[.](#elem-2.sentence-1) [3](#elem-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2882) [*Note [1](#elem-note-1)*: For the overload marked #1, if a type T in Types is some reference type X&, the return type is X&, not X&&[.](#elem-3.sentence-1) However, if the element type is a non-reference type T, the return type is T&&[.](#elem-3.sentence-2) — *end note*] [4](#elem-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2891) [*Note [2](#elem-note-2)*: Constness is shallow[.](#elem-4.sentence-1) For the overload marked #2, if a type T in Types is some reference type X&, the return type is X&, not const X&[.](#elem-4.sentence-2) However, if the element type is a non-reference type T, the return type is const T&[.](#elem-4.sentence-3) This is consistent with how constness is defined to work for non-static data members of reference type[.](#elem-4.sentence-4) — *end note*] [🔗](#lib:get,tuple_) `template constexpr T& get(tuple& t) noexcept; template constexpr T&& get(tuple&& t) noexcept; template constexpr const T& get(const tuple& t) noexcept; template constexpr const T&& get(const tuple&& t) noexcept; ` [5](#elem-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2917) *Mandates*: The type T occurs exactly once in Types[.](#elem-5.sentence-1) [6](#elem-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2921) *Returns*: A reference to the element of t corresponding to the typeT in Types[.](#elem-6.sentence-1) [7](#elem-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2926) [*Example [1](#elem-example-1)*: const tuple t(1, 2, 3.4, 5.6);const int& i1 = get(t); // OK, i1 has value 1const int& i2 = get(t); // OK, i2 has value 2const double& d = get(t); // error: type double is not unique within t — *end example*] [8](#elem-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2937) [*Note [3](#elem-note-3)*: 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[.](#elem-8.sentence-1) — *end note*] ### [22.4.9](#rel) Relational operators [[tuple.rel]](tuple.rel) [🔗](#lib:operator==,tuple) `template constexpr bool operator==(const tuple& t, const tuple& u); template constexpr bool operator==(const tuple& t, const UTuple& u); ` [1](#rel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2957) For the first overload let UTuple be tuple[.](#rel-1.sentence-1) [2](#rel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2960) *Constraints*: For all i, where 0 ≤ i < sizeof...(TTypes),get(t) == get(u) is a valid expression anddecltype(get(t) == get(u)) models [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]")[.](#rel-2.sentence-1) sizeof...(TTypes) equalstuple_size_v[.](#rel-2.sentence-2) [3](#rel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2969) *Returns*: true if get(t) == get(u) for alli, otherwise false[.](#rel-3.sentence-1) [*Note [1](#rel-note-1)*: If sizeof...(TTypes) equals zero, returns true[.](#rel-3.sentence-2) — *end note*] [4](#rel-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L2977) *Remarks*: - [(4.1)](#rel-4.1) The elementary comparisons are performed in order from the zeroth index upwards[.](#rel-4.1.sentence-1) No comparisons or element accesses are performed after the first equality comparison that evaluates tofalse[.](#rel-4.1.sentence-2) - [(4.2)](#rel-4.2) The second overload is to be found via argument-dependent lookup ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4 Argument-dependent name lookup")) only[.](#rel-4.2.sentence-1) [🔗](#lib:operator%3c=%3e,tuple) `template constexpr common_comparison_category_t...> operator<=>(const tuple& t, const tuple& u); template constexpr common_comparison_category_t...> operator<=>(const tuple& t, const UTuple& u); ` [5](#rel-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3001) For the second overload, Elems denotes the pack of typestuple_element_t<0, UTuple>,tuple_element_t<1, UTuple>, …,tuple_element_t - 1, UTuple>[.](#rel-5.sentence-1) [6](#rel-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3007) *Effects*: Performs a lexicographical comparison between t and u[.](#rel-6.sentence-1) If sizeof...(TTypes) equals zero, returns strong_ordering​::​equal[.](#rel-6.sentence-2) Otherwise, equivalent to:if (auto c = *synth-three-way*(get<0>(t), get<0>(u)); c != 0) return c;return ttail <=> utail; where rtail for some r is a tuple containing all but the first element of r[.](#rel-6.sentence-3) [7](#rel-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3020) *Remarks*: The second overload is to be found via argument-dependent lookup ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4 Argument-dependent name lookup")) only[.](#rel-7.sentence-1) [8](#rel-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3025) [*Note [2](#rel-note-2)*: The above definition does not require ttail (or utail) to be constructed[.](#rel-8.sentence-1) It might not even be possible, as t and u are not required to be copy constructible[.](#rel-8.sentence-2) Also, all comparison operator functions are short circuited; they do not perform element accesses beyond what is needed to determine the result of the comparison[.](#rel-8.sentence-3) — *end note*] ### [22.4.10](#common.ref) common_reference related specializations [[tuple.common.ref]](tuple.common.ref) [1](#common.ref-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3037) In the descriptions that follow: - [(1.1)](#common.ref-1.1) Let TTypes be a pack formed by the sequence of tuple_element_t for every integer 0≤i[.](#common.ref-1.1.sentence-1) - [(1.2)](#common.ref-1.2) Let UTypes be a pack formed by the sequence of tuple_element_t for every integer 0≤i[.](#common.ref-1.2.sentence-1) [🔗](#lib:basic_common_reference,tuple) `template<[tuple-like](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") TTuple, [tuple-like](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") UTuple, template class TQual, template class UQual> struct basic_common_reference { using type = see below; }; ` [2](#common.ref-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3061) *Constraints*: - [(2.1)](#common.ref-2.1) TTuple is a specialization of tuple orUTuple is a specialization of tuple[.](#common.ref-2.1.sentence-1) - [(2.2)](#common.ref-2.2) is_same_v> is true[.](#common.ref-2.2.sentence-1) - [(2.3)](#common.ref-2.3) is_same_v> is true[.](#common.ref-2.3.sentence-1) - [(2.4)](#common.ref-2.4) tuple_size_v equals tuple_size_v[.](#common.ref-2.4.sentence-1) - [(2.5)](#common.ref-2.5) tuple, UQual>...> denotes a type[.](#common.ref-2.5.sentence-1) The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") type denotes the typetuple, UQual>...>[.](#common.ref-2.sentence-2) [🔗](#lib:common_type,tuple) `template<[tuple-like](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") TTuple, [tuple-like](#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") UTuple> struct common_type { using type = see below; }; ` [3](#common.ref-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3090) *Constraints*: - [(3.1)](#common.ref-3.1) TTuple is a specialization of tuple orUTuple is a specialization of tuple[.](#common.ref-3.1.sentence-1) - [(3.2)](#common.ref-3.2) is_same_v> is true[.](#common.ref-3.2.sentence-1) - [(3.3)](#common.ref-3.3) is_same_v> is true[.](#common.ref-3.3.sentence-1) - [(3.4)](#common.ref-3.4) tuple_size_v equals tuple_size_v[.](#common.ref-3.4.sentence-1) - [(3.5)](#common.ref-3.5) tuple...> denotes a type[.](#common.ref-3.5.sentence-1) The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") type denotes the typetuple...>[.](#common.ref-3.sentence-2) ### [22.4.11](#traits) Tuple traits [[tuple.traits]](tuple.traits) [🔗](#lib:uses_allocator%3ctuple%3e) `template struct uses_allocator, Alloc> : true_type { }; ` [1](#traits-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3118) *Preconditions*: Alloc meets the [*Cpp17Allocator*](allocator.requirements.general#:Cpp17Allocator "16.4.4.6.1 General [allocator.requirements.general]") requirements ([[allocator.requirements.general]](allocator.requirements.general "16.4.4.6.1 General"))[.](#traits-1.sentence-1) [2](#traits-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3123) [*Note [1](#traits-note-1)*: Specialization of this trait informs other library components thattuple can be constructed with an allocator, even though it does not have a nested allocator_type[.](#traits-2.sentence-1) — *end note*] ### [22.4.12](#special) Tuple specialized algorithms [[tuple.special]](tuple.special) [🔗](#lib:swap,tuple_) `template constexpr void swap(tuple& x, tuple& y) noexcept(see below); template constexpr void swap(const tuple& x, const tuple& y) noexcept(see below); ` [1](#special-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3142) *Constraints*: - [(1.1)](#special-1.1) For the first overload,(is_swappable_v && ...) is true[.](#special-1.1.sentence-1) - [(1.2)](#special-1.2) For the second overload,(is_swappable_v && ...) is true[.](#special-1.2.sentence-1) [2](#special-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3153) *Effects*: As if by x.swap(y)[.](#special-2.sentence-1) [3](#special-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L3157) *Remarks*: The exception specification is equivalent to:noexcept(x.swap(y))