[utility] # 22 General utilities library [[utilities]](./#utilities) ## 22.2 Utility components [utility] ### [22.2.1](#syn) Header synopsis [[utility.syn]](utility.syn) [1](#syn-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L29) The header contains some basic function and class templates that are used throughout the rest of the library[.](#syn-1.sentence-1) // all freestanding#include // see [[compare.syn]](compare.syn "17.12.1 Header synopsis")#include // see [[initializer.list.syn]](initializer.list.syn "17.11.2 Header synopsis")namespace std {// [[utility.swap]](#swap "22.2.2 swap"), swaptemplateconstexpr void swap(T& a, T& b) noexcept(*see below*); templateconstexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v); // [[utility.exchange]](#exchange "22.2.3 exchange"), exchangetemplateconstexpr T exchange(T& obj, U&& new_val) noexcept(*see below*); // [[forward]](#forward "22.2.4 Forward/move helpers"), forward/movetemplateconstexpr T&& forward(remove_reference_t& t) noexcept; templateconstexpr T&& forward(remove_reference_t&& t) noexcept; templateconstexpr auto forward_like(U&& x) noexcept -> *see below*; templateconstexpr remove_reference_t&& move(T&&) noexcept; templateconstexpr conditional_t && is_copy_constructible_v, const T&, T&&> move_if_noexcept(T& x) noexcept; // [[utility.as.const]](#as.const "22.2.5 Function template as_­const"), as_consttemplateconstexpr add_const_t& as_const(T& t) noexcept; templatevoid as_const(const T&&) = delete; // [[declval]](#declval "22.2.6 Function template declval"), declvaltemplate add_rvalue_reference_t declval() noexcept; // as unevaluated operand// [[utility.intcmp]](#intcmp "22.2.7 Integer comparison functions"), integer comparison functionstemplateconstexpr bool cmp_equal(T t, U u) noexcept; templateconstexpr bool cmp_not_equal(T t, U u) noexcept; templateconstexpr bool cmp_less(T t, U u) noexcept; templateconstexpr bool cmp_greater(T t, U u) noexcept; templateconstexpr bool cmp_less_equal(T t, U u) noexcept; templateconstexpr bool cmp_greater_equal(T t, U u) noexcept; templateconstexpr bool in_range(T t) noexcept; // [[utility.underlying]](#underlying "22.2.8 Function template to_­underlying"), to_underlyingtemplateconstexpr underlying_type_t to_underlying(T value) noexcept; // [[utility.undefined]](#undefined "22.2.9 Undefined behavior"), undefined behavior[[noreturn]] void unreachable(); void observable_checkpoint() noexcept; // [[intseq]](intseq "21.2 Compile-time integer sequences"), compile-time integer sequencestemplatestruct integer_sequence; templateusing [index_sequence](#lib:index_sequence "22.2.1 Header synopsis [utility.syn]") = integer_sequence; templateusing make_integer_sequence = integer_sequence; templateusing [make_index_sequence](#lib:make_index_sequence "22.2.1 Header synopsis [utility.syn]") = make_integer_sequence; templateusing [index_sequence_for](#lib:index_sequence_for "22.2.1 Header synopsis [utility.syn]") = make_index_sequence; // [[pairs]](pairs "22.3 Pairs"), class template pairtemplatestruct pair; template class TQual, template class UQual>requires requires { typename pair, UQual>, common_reference_t, UQual>>; }struct basic_common_reference, pair, TQual, UQual> {using type = pair, UQual>, common_reference_t, UQual>>; }; templaterequires requires { typename pair, common_type_t>; }struct common_type, pair> {using type = pair, common_type_t>; }; // [[pairs.spec]](pairs.spec "22.3.3 Specialized algorithms"), pair specialized algorithmstemplateconstexpr bool operator==(const pair&, const pair&); templateconstexpr common_comparison_category_t<*synth-three-way-result*, *synth-three-way-result*>operator<=>(const pair&, const pair&); templateconstexpr void swap(pair& x, pair& y) noexcept(noexcept(x.swap(y))); templateconstexpr void swap(const pair& x, const pair& y)noexcept(noexcept(x.swap(y))); templateconstexpr *see below* make_pair(T1&&, T2&&); // [[pair.astuple]](pair.astuple "22.3.4 Tuple-like access to pair"), tuple-like access to pairtemplate struct tuple_size; template struct tuple_element; template struct tuple_size>; template struct tuple_element>; templateconstexpr tuple_element_t>& get(pair&) noexcept; templateconstexpr tuple_element_t>&& get(pair&&) noexcept; templateconstexpr const tuple_element_t>& get(const pair&) noexcept; templateconstexpr const tuple_element_t>&& get(const pair&&) noexcept; templateconstexpr T1& get(pair& p) noexcept; templateconstexpr const T1& get(const pair& p) noexcept; templateconstexpr T1&& get(pair&& p) noexcept; templateconstexpr const T1&& get(const pair&& p) noexcept; templateconstexpr T2& get(pair& p) noexcept; templateconstexpr const T2& get(const pair& p) noexcept; templateconstexpr T2&& get(pair&& p) noexcept; templateconstexpr const T2&& get(const pair&& p) noexcept; // [[pair.piecewise]](pair.piecewise "22.3.5 Piecewise construction"), pair piecewise constructionstruct piecewise_construct_t {explicit piecewise_construct_t() = default; }; inline constexpr piecewise_construct_t piecewise_construct{}; template class tuple; // defined in [](tuple.syn#header:%3ctuple%3e "22.4.2 Header synopsis [tuple.syn]")// in-place constructionstruct in_place_t {explicit in_place_t() = default; }; inline constexpr in_place_t in_place{}; templatestruct in_place_type_t {explicit in_place_type_t() = default; }; template constexpr in_place_type_t in_place_type{}; templatestruct in_place_index_t {explicit in_place_index_t() = default; }; template constexpr in_place_index_t in_place_index{}; // nontype argument tagtemplatestruct nontype_t {explicit nontype_t() = default; }; template constexpr nontype_t nontype{}; // [[variant.monostate]](variant.monostate "22.6.8 Class monostate"), class monostatestruct monostate; // [[variant.monostate.relops]](variant.monostate.relops "22.6.9 monostate relational operators"), monostate relational operatorsconstexpr bool operator==(monostate, monostate) noexcept; constexpr strong_ordering operator<=>(monostate, monostate) noexcept; // [[variant.hash]](variant.hash "22.6.12 Hash support"), hash supporttemplate struct hash; template<> struct hash;} ### [22.2.2](#swap) swap [[utility.swap]](utility.swap) [🔗](#lib:swap) `template constexpr void swap(T& a, T& b) noexcept(see below); ` [1](#swap-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L251) *Constraints*: is_move_constructible_v is true andis_move_assignable_v is true[.](#swap-1.sentence-1) [2](#swap-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L256) *Preconditions*: TypeT meets the[*Cpp17MoveConstructible*](utility.arg.requirements#:Cpp17MoveConstructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") (Table [31](utility.arg.requirements#tab:cpp17.moveconstructible "Table 31: Cpp17MoveConstructible requirements")) and[*Cpp17MoveAssignable*](utility.arg.requirements#:Cpp17MoveAssignable "16.4.4.2 Template argument requirements [utility.arg.requirements]") (Table [33](utility.arg.requirements#tab:cpp17.moveassignable "Table 33: Cpp17MoveAssignable requirements")) requirements[.](#swap-2.sentence-1) [3](#swap-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L266) *Effects*: Exchanges values stored in two locations[.](#swap-3.sentence-1) [4](#swap-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L270) *Remarks*: The exception specification is equivalent to:is_nothrow_move_constructible_v && is_nothrow_move_assignable_v [🔗](#lib:swap_) `template constexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v); ` [5](#swap-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L285) *Constraints*: is_swappable_v is true[.](#swap-5.sentence-1) [6](#swap-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L289) *Preconditions*: a[i] is swappable with ([[swappable.requirements]](swappable.requirements "16.4.4.3 Swappable requirements")) b[i] for all i in the range [0, N)[.](#swap-6.sentence-1) [7](#swap-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L294) *Effects*: As if by swap_ranges(a, a + N, b)[.](#swap-7.sentence-1) ### [22.2.3](#exchange) exchange [[utility.exchange]](utility.exchange) [🔗](#lib:exchange) `template constexpr T exchange(T& obj, U&& new_val) noexcept(see below); ` [1](#exchange-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L308) *Effects*: Equivalent to:T old_val = std::move(obj); obj = std::forward(new_val);return old_val; [2](#exchange-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L317) *Remarks*: The exception specification is equivalent to:is_nothrow_move_constructible_v && is_nothrow_assignable_v ### [22.2.4](#forward) Forward/move helpers [[forward]](forward) [1](#forward-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L328) The library provides templated helper functions to simplify applying move semantics to an lvalue and to simplify the implementation of forwarding functions[.](#forward-1.sentence-1) All functions specified in this subclause are [signal-safe](support.signal#def:evaluation,signal-safe "17.14.5 Signal handlers [support.signal]")[.](#forward-1.sentence-2) [🔗](#lib:forward) `template constexpr T&& forward(remove_reference_t& t) noexcept; template constexpr T&& forward(remove_reference_t&& t) noexcept; ` [2](#forward-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L345) *Mandates*: For the second overload, is_lvalue_reference_v is false[.](#forward-2.sentence-1) [3](#forward-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L349) *Returns*: static_cast(t)[.](#forward-3.sentence-1) [4](#forward-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L353) [*Example [1](#forward-example-1)*: template shared_ptr factory(A1&& a1, A2&& a2) {return shared_ptr(new T(std::forward(a1), std::forward(a2)));}struct A { A(int&, const double&);}; void g() { shared_ptr sp1 = factory(2, 1.414); // error: 2 will not bind to int&int i = 2; shared_ptr sp2 = factory(i, 1.414); // OK} In the first call to factory,A1 is deduced as int, so 2 is forwarded to A's constructor as an rvalue[.](#forward-4.sentence-1) In the second call to factory,A1 is deduced as int&, so i is forwarded to A's constructor as an lvalue[.](#forward-4.sentence-2) In both cases, A2 is deduced as double, so 1.414 is forwarded to A's constructor as an rvalue[.](#forward-4.sentence-3) — *end example*] [🔗](#lib:forward_like) `template constexpr auto forward_like(U&& x) noexcept -> see below; ` [5](#forward-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L389) *Mandates*: T is a referenceable type ([[defns.referenceable]](defns.referenceable "3.45 referenceable type"))[.](#forward-5.sentence-1) [6](#forward-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L393) - [(6.1)](#forward-6.1) Let *COPY_CONST*(A, B) be const B if A is a const type, otherwise B[.](#forward-6.1.sentence-1) - [(6.2)](#forward-6.2) Let *OVERRIDE_REF*(A, B) be remove_reference_t&& if A is an rvalue reference type, otherwise B&[.](#forward-6.2.sentence-1) - [(6.3)](#forward-6.3) Let V be*OVERRIDE_REF*(T&&, *COPY_CONST*(remove_reference_t, remove_reference_t)) [7](#forward-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L408) *Returns*: static_cast(x)[.](#forward-7.sentence-1) [8](#forward-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L412) *Remarks*: The return type is V[.](#forward-8.sentence-1) [9](#forward-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L416) [*Example [2](#forward-example-2)*: struct accessor { vector* container; decltype(auto) operator[](this auto&& self, size_t i) {return std::forward_like((*container)[i]); }};void g() { vector v{"a"s, "b"s}; accessor a{&v}; string& x = a[0]; // OK, binds to lvalue reference string&& y = std::move(a)[0]; // OK, is rvalue reference string const&& z = std::move(as_const(a))[1]; // OK, is const&& string& w = as_const(a)[1]; // error: will not bind to non-const} — *end example*] [🔗](#lib:move,function) `template constexpr remove_reference_t&& move(T&& t) noexcept; ` [10](#forward-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L444) *Returns*: static_cast&&>(t)[.](#forward-10.sentence-1) [11](#forward-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L448) [*Example [3](#forward-example-3)*: template shared_ptr factory(A1&& a1) {return shared_ptr(new T(std::forward(a1)));}struct A { A(); A(const A&); // copies from lvalues A(A&&); // moves from rvalues}; void g() { A a; shared_ptr sp1 = factory(a); // “a'' binds to A(const A&) shared_ptr sp2 = factory(std::move(a)); // “a'' binds to A(A&&)} In the first call to factory,A1 is deduced as A&, so a is forwarded as a non-const lvalue[.](#forward-11.sentence-1) This binds to the constructor A(const A&), which copies the value from a[.](#forward-11.sentence-2) In the second call to factory, because of the callstd​::​move(a),A1 is deduced as A, so a is forwarded as an rvalue[.](#forward-11.sentence-3) This binds to the constructor A(A&&), which moves the value from a[.](#forward-11.sentence-4) — *end example*] [🔗](#lib:move_if_noexcept) `template constexpr conditional_t< !is_nothrow_move_constructible_v && is_copy_constructible_v, const T&, T&&> move_if_noexcept(T& x) noexcept; ` [12](#forward-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L488) *Returns*: std​::​move(x)[.](#forward-12.sentence-1) ### [22.2.5](#as.const) Function template as_const [[utility.as.const]](utility.as.const) [🔗](#lib:as_const) `template constexpr add_const_t& as_const(T& t) noexcept; ` [1](#as.const-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L501) *Returns*: t[.](#as.const-1.sentence-1) ### [22.2.6](#declval) Function template declval [[declval]](declval) [1](#declval-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L508) The library provides the function template declval to simplify the definition of expressions which occur as [unevaluated operands](expr.context#def:unevaluated_operand "7.2.3 Context dependence [expr.context]")[.](#declval-1.sentence-1) [🔗](#lib:declval) `template add_rvalue_reference_t declval() noexcept; // as unevaluated operand ` [2](#declval-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L518) *Mandates*: This function is not odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule"))[.](#declval-2.sentence-1) [3](#declval-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L522) *Remarks*: The template parameter T of declval may be an incomplete type[.](#declval-3.sentence-1) [4](#declval-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L526) [*Example [1](#declval-example-1)*: template decltype(static_cast(declval())) convert(From&&); declares a function template convert which only participates in overload resolution if the type From can be explicitly converted to type To[.](#declval-4.sentence-1) For another example see class template common_type ([[meta.trans.other]](meta.trans.other "21.3.9.7 Other transformations"))[.](#declval-4.sentence-2) — *end example*] ### [22.2.7](#intcmp) Integer comparison functions [[utility.intcmp]](utility.intcmp) [🔗](#lib:cmp_equal) `template constexpr bool cmp_equal(T t, U u) noexcept; ` [1](#intcmp-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L546) *Mandates*: Both T and U are standard integer types or extended integer types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#intcmp-1.sentence-1) [2](#intcmp-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L551) *Effects*: Equivalent to:using UT = make_unsigned_t;using UU = make_unsigned_t;if constexpr (is_signed_v == is_signed_v)return t == u;else if constexpr (is_signed_v)return t < 0 ? false : UT(t) == u;elsereturn u < 0 ? false : t == UU(u); [🔗](#lib:cmp_not_equal) `template constexpr bool cmp_not_equal(T t, U u) noexcept; ` [3](#intcmp-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L573) *Effects*: Equivalent to: return !cmp_equal(t, u); [🔗](#lib:cmp_less) `template constexpr bool cmp_less(T t, U u) noexcept; ` [4](#intcmp-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L585) *Mandates*: Both T and U are standard integer types or extended integer types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#intcmp-4.sentence-1) [5](#intcmp-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L590) *Effects*: Equivalent to:using UT = make_unsigned_t;using UU = make_unsigned_t;if constexpr (is_signed_v == is_signed_v)return t < u;else if constexpr (is_signed_v)return t < 0 ? true : UT(t) < u;elsereturn u < 0 ? false : t < UU(u); [🔗](#lib:cmp_greater) `template constexpr bool cmp_greater(T t, U u) noexcept; ` [6](#intcmp-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L612) *Effects*: Equivalent to: return cmp_less(u, t); [🔗](#lib:cmp_less_equal) `template constexpr bool cmp_less_equal(T t, U u) noexcept; ` [7](#intcmp-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L624) *Effects*: Equivalent to: return !cmp_greater(t, u); [🔗](#lib:cmp_greater_equal) `template constexpr bool cmp_greater_equal(T t, U u) noexcept; ` [8](#intcmp-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L636) *Effects*: Equivalent to: return !cmp_less(t, u); [🔗](#lib:in_range) `template constexpr bool in_range(T t) noexcept; ` [9](#intcmp-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L648) *Mandates*: Both T and R are standard integer types or extended integer types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#intcmp-9.sentence-1) [10](#intcmp-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L653) *Effects*: Equivalent to:return cmp_greater_equal(t, numeric_limits::min()) && cmp_less_equal(t, numeric_limits::max()); [11](#intcmp-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L662) [*Note [1](#intcmp-note-1)*: These function templates cannot be used to comparebyte,char,char8_t,char16_t,char32_t,wchar_t, andbool[.](#intcmp-11.sentence-1) — *end note*] ### [22.2.8](#underlying) Function template to_underlying [[utility.underlying]](utility.underlying) [🔗](#lib:to_underlying) `template constexpr underlying_type_t to_underlying(T value) noexcept; ` [1](#underlying-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L683) *Returns*: static_cast>(value)[.](#underlying-1.sentence-1) ### [22.2.9](#undefined) Undefined behavior [[utility.undefined]](utility.undefined) [🔗](#lib:unreachable) `[[noreturn]] void unreachable(); ` [1](#undefined-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L696) *Preconditions*: false is true[.](#undefined-1.sentence-1) [*Note [1](#undefined-note-1)*: This precondition cannot be satisfied, thus the behavior of calling unreachable is undefined[.](#undefined-1.sentence-2) — *end note*] [2](#undefined-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L704) [*Example [1](#undefined-example-1)*: int f(int x) {switch (x) {case 0:case 1:return x; default: std::unreachable(); }}int a = f(1); // OK, a has value 1int b = f(3); // undefined behavior — *end example*] [🔗](#lib:observable_checkpoint) `void observable_checkpoint() noexcept; ` [3](#undefined-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L728) *Effects*: Establishes an observable checkpoint ([[intro.abstract]](intro.abstract "4.1.2 Abstract machine"))[.](#undefined-3.sentence-1)