24 KiB
[utility]
22 General utilities library [utilities]
22.2 Utility components [utility]
22.2.1 Header synopsis [utility.syn]
The header contains some basic function and class templates that are used throughout the rest of the library.
// all freestanding#include // see [compare.syn]#include <initializer_list> // see [initializer.list.syn]namespace std {// [utility.swap], swaptemplateconstexpr void swap(T& a, T& b) noexcept(see below); template<class T, size_t N>constexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v); // [utility.exchange], exchangetemplate<class T, class U = T>constexpr T exchange(T& obj, U&& new_val) noexcept(see below); // [forward], forward/movetemplateconstexpr T&& forward(remove_reference_t& t) noexcept; templateconstexpr T&& forward(remove_reference_t&& t) noexcept; template<class T, class U>constexpr auto forward_like(U&& x) noexcept -> see below; templateconstexpr remove_reference_t&& move(T&&) noexcept; templateconstexpr conditional_t<!is_nothrow_move_constructible_v && is_copy_constructible_v, const T&, T&&> move_if_noexcept(T& x) noexcept; // [utility.as.const], as_consttemplateconstexpr add_const_t& as_const(T& t) noexcept; templatevoid as_const(const T&&) = delete; // [declval], declvaltemplate add_rvalue_reference_t declval() noexcept; // as unevaluated operand// [utility.intcmp], integer comparison functionstemplate<class T, class U>constexpr bool cmp_equal(T t, U u) noexcept; template<class T, class U>constexpr bool cmp_not_equal(T t, U u) noexcept; template<class T, class U>constexpr bool cmp_less(T t, U u) noexcept; template<class T, class U>constexpr bool cmp_greater(T t, U u) noexcept; template<class T, class U>constexpr bool cmp_less_equal(T t, U u) noexcept; template<class T, class U>constexpr bool cmp_greater_equal(T t, U u) noexcept; template<class R, class T>constexpr bool in_range(T t) noexcept; // [utility.underlying], to_underlyingtemplateconstexpr underlying_type_t to_underlying(T value) noexcept; // [utility.undefined], undefined behaviornoreturn void unreachable(); void observable_checkpoint() noexcept; // [intseq], compile-time integer sequencestemplate<class T, T...>struct integer_sequence; template<size_t... I>using index_sequence = integer_sequence<size_t, I...>; template<class T, T N>using make_integer_sequence = integer_sequence<T, see below>; template<size_t N>using make_index_sequence = make_integer_sequence<size_t, N>; template<class... T>using index_sequence_for = make_index_sequence<sizeof...(T)>; // [pairs], class template pairtemplate<class T1, class T2>struct pair; template<class T1, class T2, class U1, class U2, template class TQual, template class UQual>requires requires { typename pair<common_reference_t<TQual, UQual>, common_reference_t<TQual, UQual>>; }struct basic_common_reference<pair<T1, T2>, pair<U1, U2>, TQual, UQual> {using type = pair<common_reference_t<TQual, UQual>, common_reference_t<TQual, UQual>>; }; template<class T1, class T2, class U1, class U2>requires requires { typename pair<common_type_t<T1, U1>, common_type_t<T2, U2>>; }struct common_type<pair<T1, T2>, pair<U1, U2>> {using type = pair<common_type_t<T1, U1>, common_type_t<T2, U2>>; }; // [pairs.spec], pair specialized algorithmstemplate<class T1, class T2, class U1, class U2>constexpr bool operator==(const pair<T1, T2>&, const pair<U1, U2>&); template<class T1, class T2, class U1, class U2>constexpr common_comparison_category_t<synth-three-way-result<T1, U1>, synth-three-way-result<T2, U2>>operator<=>(const pair<T1, T2>&, const pair<U1, U2>&); template<class T1, class T2>constexpr void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); template<class T1, class T2>constexpr void swap(const pair<T1, T2>& x, const pair<T1, T2>& y)noexcept(noexcept(x.swap(y))); template<class T1, class T2>constexpr see below make_pair(T1&&, T2&&); // [pair.astuple], tuple-like access to pairtemplate struct tuple_size; template<size_t I, class T> struct tuple_element; template<class T1, class T2> struct tuple_size<pair<T1, T2>>; template<size_t I, class T1, class T2> struct tuple_element<I, pair<T1, T2>>; template<size_t I, class T1, class T2>constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>&) noexcept; template<size_t I, class T1, class T2>constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&&) noexcept; template<size_t I, class T1, class T2>constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>&) noexcept; template<size_t I, class T1, class T2>constexpr const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&&) noexcept; template<class T1, class T2>constexpr T1& get(pair<T1, T2>& p) noexcept; template<class T1, class T2>constexpr const T1& get(const pair<T1, T2>& p) noexcept; template<class T1, class T2>constexpr T1&& get(pair<T1, T2>&& p) noexcept; template<class T1, class T2>constexpr const T1&& get(const pair<T1, T2>&& p) noexcept; template<class T2, class T1>constexpr T2& get(pair<T1, T2>& p) noexcept; template<class T2, class T1>constexpr const T2& get(const pair<T1, T2>& p) noexcept; template<class T2, class T1>constexpr T2&& get(pair<T1, T2>&& p) noexcept; template<class T2, class T1>constexpr const T2&& get(const pair<T1, T2>&& p) noexcept; // [pair.piecewise], pair piecewise constructionstruct piecewise_construct_t {explicit piecewise_construct_t() = default; }; inline constexpr piecewise_construct_t piecewise_construct{}; template<class... Types> class tuple; // defined in // 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{}; template<size_t I>struct in_place_index_t {explicit in_place_index_t() = default; }; template<size_t I> constexpr in_place_index_t in_place_index{}; // nontype argument tagtemplatestruct nontype_t {explicit nontype_t() = default; }; template constexpr nontype_t nontype{}; // [variant.monostate], class monostatestruct monostate; // [variant.monostate.relops], monostate relational operatorsconstexpr bool operator==(monostate, monostate) noexcept; constexpr strong_ordering operator<=>(monostate, monostate) noexcept; // [variant.hash], hash supporttemplate struct hash; template<> struct hash;}
22.2.2 swap [utility.swap]
template<class T> constexpr void swap(T& a, T& b) noexcept(see below);
Constraints: is_move_constructible_v is true andis_move_assignable_v is true.
Preconditions: TypeT meets theCpp17MoveConstructible (Table 31) andCpp17MoveAssignable (Table 33) requirements.
Effects: Exchanges values stored in two locations.
Remarks: The exception specification is equivalent to:is_nothrow_move_constructible_v && is_nothrow_move_assignable_v
template<class T, size_t N> constexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v<T>);
Constraints: is_swappable_v is true.
Preconditions: a[i] is swappable with ([swappable.requirements]) b[i] for all i in the range [0, N).
Effects: As if by swap_ranges(a, a + N, b).
22.2.3 exchange [utility.exchange]
template<class T, class U = T> constexpr T exchange(T& obj, U&& new_val) noexcept(see below);
Effects: Equivalent to:T old_val = std::move(obj); obj = std::forward(new_val);return old_val;
Remarks: The exception specification is equivalent to:is_nothrow_move_constructible_v && is_nothrow_assignable_v<T&, U>
22.2.4 Forward/move helpers [forward]
The library provides templated helper functions to simplify applying move semantics to an lvalue and to simplify the implementation of forwarding functions.
All functions specified in this subclause are signal-safe.
template<class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept; template<class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept;
Mandates: For the second overload, is_lvalue_reference_v is false.
Returns: static_cast<T&&>(t).
[Example 1: template<class T, class A1, class A2> 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.
In the second call to factory,A1 is deduced as int&, so i is forwarded to A's constructor as an lvalue.
In both cases, A2 is deduced as double, so 1.414 is forwarded to A's constructor as an rvalue.
â end example]
template<class T, class U> constexpr auto forward_like(U&& x) noexcept -> see below;
Mandates: T is a referenceable type ([defns.referenceable]).
-
Let COPY_CONST(A, B) be const B if A is a const type, otherwise B.
-
Let OVERRIDE_REF(A, B) be remove_reference_t&& if A is an rvalue reference type, otherwise B&.
-
Let V beOVERRIDE_REF(T&&, COPY_CONST(remove_reference_t, remove_reference_t))
Returns: static_cast(x).
Remarks: The return type is V.
[Example 2: struct accessor { vector* container; decltype(auto) operator[](this auto&& self, size_t i) {return std::forward_like<decltype(self)>((*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]
template<class T> constexpr remove_reference_t<T>&& move(T&& t) noexcept;
Returns: static_cast<remove_reference_t&&>(t).
[Example 3: template<class T, class A1> 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.
This binds to the constructor A(const A&), which copies the value from a.
In the second call to factory, because of the callstd::move(a),A1 is deduced as A, so a is forwarded as an rvalue.
This binds to the constructor A(A&&), which moves the value from a.
â end example]
template<class T> constexpr conditional_t< !is_nothrow_move_constructible_v<T> && is_copy_constructible_v<T>, const T&, T&&> move_if_noexcept(T& x) noexcept;
Returns: std::move(x).
22.2.5 Function template as_const [utility.as.const]
template<class T> constexpr add_const_t<T>& as_const(T& t) noexcept;
Returns: t.
22.2.6 Function template declval [declval]
The library provides the function template declval to simplify the definition of expressions which occur as unevaluated operands.
template<class T> add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand
Mandates: This function is not odr-used ([basic.def.odr]).
Remarks: The template parameter T of declval may be an incomplete type.
[Example 1:
template<class To, class From> 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.
For another example see class template common_type ([meta.trans.other]).
â end example]
22.2.7 Integer comparison functions [utility.intcmp]
template<class T, class U> constexpr bool cmp_equal(T t, U u) noexcept;
Mandates: Both T and U are standard integer types or extended integer types ([basic.fundamental]).
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);
template<class T, class U> constexpr bool cmp_not_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_equal(t, u);
template<class T, class U> constexpr bool cmp_less(T t, U u) noexcept;
Mandates: Both T and U are standard integer types or extended integer types ([basic.fundamental]).
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);
template<class T, class U> constexpr bool cmp_greater(T t, U u) noexcept;
Effects: Equivalent to: return cmp_less(u, t);
template<class T, class U> constexpr bool cmp_less_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_greater(t, u);
template<class T, class U> constexpr bool cmp_greater_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_less(t, u);
template<class R, class T> constexpr bool in_range(T t) noexcept;
Mandates: Both T and R are standard integer types or extended integer types ([basic.fundamental]).
Effects: Equivalent to:return cmp_greater_equal(t, numeric_limits::min()) && cmp_less_equal(t, numeric_limits::max());
[Note 1:
These function templates cannot be used to comparebyte,char,char8_t,char16_t,char32_t,wchar_t, andbool.
â end note]
22.2.8 Function template to_underlying [utility.underlying]
template<class T> constexpr underlying_type_t<T> to_underlying(T value) noexcept;
Returns: static_cast<underlying_type_t>(value).
22.2.9 Undefined behavior [utility.undefined]
[[noreturn]] void unreachable();
Preconditions: false is true.
[Note 1:
This precondition cannot be satisfied, thus the behavior of calling unreachable is undefined.
â end note]
[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]
void observable_checkpoint() noexcept;
Effects: Establishes an observable checkpoint ([intro.abstract]).