[utility]

# 22 General utilities library [[utilities]](./#utilities)

## 22.2 Utility components [utility]

### [22.2.1](#syn) Header <utility> synopsis [[utility.syn]](utility.syn)

[1](#syn-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L29)

The header <utility> contains some basic function and class templates that are used
throughout the rest of the library[.](#syn-1.sentence-1)

// all freestanding#include <compare> // see [[compare.syn]](compare.syn "17.12.1 Header <compare> synopsis")#include <initializer_list> // see [[initializer.list.syn]](initializer.list.syn "17.11.2 Header <initializer_­list> synopsis")namespace std {// [[utility.swap]](#swap "22.2.2 swap"), swaptemplate<class T>constexpr 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<T>); // [[utility.exchange]](#exchange "22.2.3 exchange"), exchangetemplate<class T, class U = T>constexpr T exchange(T& obj, U&& new_val) noexcept(*see below*); // [[forward]](#forward "22.2.4 Forward/move helpers"), forward/movetemplate<class T>constexpr T&& forward(remove_reference_t<T>& t) noexcept; template<class T>constexpr T&& forward(remove_reference_t<T>&& t) noexcept; template<class T, class U>constexpr auto forward_like(U&& x) noexcept -> *see below*; template<class T>constexpr remove_reference_t<T>&& move(T&&) noexcept; 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; // [[utility.as.const]](#as.const "22.2.5 Function template as_­const"), as_consttemplate<class T>constexpr add_const_t<T>& as_const(T& t) noexcept; template<class T>void as_const(const T&&) = delete; // [[declval]](#declval "22.2.6 Function template declval"), declvaltemplate<class T> add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand// [[utility.intcmp]](#intcmp "22.2.7 Integer comparison functions"), 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]](#underlying "22.2.8 Function template to_­underlying"), to_underlyingtemplate<class T>constexpr underlying_type_t<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 sequencestemplate<class T, T...>struct integer_sequence; template<size_t... I>using [index_sequence](#lib:index_sequence "22.2.1 Header <utility> synopsis [utility.syn]") = 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](#lib:make_index_sequence "22.2.1 Header <utility> synopsis [utility.syn]") = make_integer_sequence<size_t, N>; template<class... T>using [index_sequence_for](#lib:index_sequence_for "22.2.1 Header <utility> synopsis [utility.syn]") = make_index_sequence<sizeof...(T)>; // [[pairs]](pairs "22.3 Pairs"), class template pairtemplate<class T1, class T2>struct pair; template<class T1, class T2, class U1, class U2, template<class> class TQual, template<class> class UQual>requires requires { typename pair<common_reference_t<TQual<T1>, UQual<U1>>,
 common_reference_t<TQual<T2>, UQual<U2>>>; }struct basic_common_reference<pair<T1, T2>, pair<U1, U2>, TQual, UQual> {using type = pair<common_reference_t<TQual<T1>, UQual<U1>>,
 common_reference_t<TQual<T2>, UQual<U2>>>; }; 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]](pairs.spec "22.3.3 Specialized algorithms"), 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]](pair.astuple "22.3.4 Tuple-like access to pair"), tuple-like access to pairtemplate<class T> 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 "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... Types> class tuple; // defined in [<tuple>](tuple.syn#header:%3ctuple%3e "22.4.2 Header <tuple> synopsis [tuple.syn]")// in-place constructionstruct in_place_t {explicit in_place_t() = default; }; inline constexpr in_place_t in_place{}; template<class T>struct in_place_type_t {explicit in_place_type_t() = default; }; template<class T> constexpr in_place_type_t<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<I> in_place_index{}; // nontype argument tagtemplate<auto V>struct nontype_t {explicit nontype_t() = default; }; template<auto V> constexpr nontype_t<V> 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<class T> struct hash; template<> struct hash<monostate>;}

### [22.2.2](#swap) swap [[utility.swap]](utility.swap)

[ð](#lib:swap)

`template<class T>
  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<T> is true andis_move_assignable_v<T> 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<T> && is_nothrow_move_assignable_v<T>

[ð](#lib:swap_)

`template<class T, size_t N>
  constexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v<T>);
`

[5](#swap-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L285)

*Constraints*: is_swappable_v<T> 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<class T, class U = T>
  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<U>(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<T> && is_nothrow_assignable_v<T&, U>

### [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<class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept;
template<class T> constexpr T&& forward(remove_reference_t<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<T> is false[.](#forward-2.sentence-1)

[3](#forward-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L349)

*Returns*: static_cast<T&&>(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<class T, class A1, class A2> shared_ptr<T> factory(A1&& a1, A2&& a2) {return shared_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2)));}struct A { A(int&, const double&);};

void g() { shared_ptr<A> sp1 = factory<A>(2, 1.414); // error: 2 will not bind to int&int i = 2;
 shared_ptr<A> sp2 = factory<A>(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<class T, class U>
  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<B>&& 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<T>, remove_reference_t<U>))

[7](#forward-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L408)

*Returns*: static_cast<V>(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<string>* 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*]

[ð](#lib:move,function)

`template<class T> constexpr remove_reference_t<T>&& move(T&& t) noexcept;
`

[10](#forward-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L444)

*Returns*: static_cast<remove_reference_t<T>&&>(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<class T, class A1> shared_ptr<T> factory(A1&& a1) {return shared_ptr<T>(new T(std::forward<A1>(a1)));}struct A { A();
 A(const A&); // copies from lvalues A(A&&); // moves from rvalues};

void g() { A a;
 shared_ptr<A> sp1 = factory<A>(a); // âa'' binds to A(const A&) shared_ptr<A> sp2 = factory<A>(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<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;
`

[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<class T> constexpr add_const_t<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<class T> add_rvalue_reference_t<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<class To, class From> decltype(static_cast<To>(declval<From>())) 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<class T, class U>
  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<T>;using UU = make_unsigned_t<U>;if constexpr (is_signed_v<T> == is_signed_v<U>)return t == u;else if constexpr (is_signed_v<T>)return t < 0 ? false : UT(t) == u;elsereturn u < 0 ? false : t == UU(u);

[ð](#lib:cmp_not_equal)

`template<class T, class U>
  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<class T, class U>
  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<T>;using UU = make_unsigned_t<U>;if constexpr (is_signed_v<T> == is_signed_v<U>)return t < u;else if constexpr (is_signed_v<T>)return t < 0 ? true : UT(t) < u;elsereturn u < 0 ? false : t < UU(u);

[ð](#lib:cmp_greater)

`template<class T, class U>
  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<class T, class U>
  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<class T, class U>
  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<class R, class T>
  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<R>::min()) && cmp_less_equal(t, numeric_limits<R>::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<class T>
  constexpr underlying_type_t<T> to_underlying(T value) noexcept;
`

[1](#underlying-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L683)

*Returns*: static_cast<underlying_type_t<T>>(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)
