20 General utilities library [utilities]

20.1 General [utilities.general]

This Clause describes utilities that are generally useful in C++ programs; some of these utilities are used by other elements of the C++ standard library.
These utilities are summarized in Table 41.
Table 41: General utilities library summary [tab:utilities.summary]
Subclause
Header
Utility components
<utility>
Compile-time integer sequences
Pairs
Tuples
<tuple>
Optional objects
<optional>
Variants
<variant>
Storage for any type
<any>
Fixed-size sequences of bits
<bitset>
Memory
<cstdlib>, <memory>
Smart pointers
<memory>
Memory resources
<memory_­resource>
Scoped allocators
<scoped_­allocator>
Function objects
<functional>
Type traits
<type_­traits>
Compile-time rational arithmetic
<ratio>
Type indexes
<typeindex>
Execution policies
<execution>
Primitive numeric conversions
<charconv>
Formatting
<format>

20.2 Utility components [utility]

20.2.1 Header <utility> synopsis [utility.syn]

The header <utility> contains some basic function and class templates that are used throughout the rest of the library.
#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [utility.swap], swap template<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 template<class T, class U = T> constexpr T exchange(T& obj, U&& new_val); // [forward], forward/move template<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> 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 template<class T> constexpr add_const_t<T>& as_const(T& t) noexcept; template<class T> void as_const(const T&&) = delete; // [declval], declval template<class T> add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand // [utility.intcmp], integer comparison functions template<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; // [intseq], compile-time integer sequences template<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 pair template<class T1, class T2> struct pair; // [pairs.spec], pair specialized algorithms template<class T1, class T2> constexpr bool operator==(const pair<T1, T2>&, const pair<T1, T2>&); template<class T1, class T2> constexpr common_comparison_category_t<synth-three-way-result<T1>, synth-three-way-result<T2>> operator<=>(const pair<T1, T2>&, const pair<T1, T2>&); 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 see below make_pair(T1&&, T2&&); // [pair.astuple], tuple-like access to pair template<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 construction struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; inline constexpr piecewise_construct_t piecewise_construct{}; template<class... Types> class tuple; // defined in <tuple> // in-place construction struct 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> inline 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> inline constexpr in_place_index_t<I> in_place_index{}; }

20.2.2 swap [utility.swap]

template<class T> constexpr void swap(T& a, T& b) noexcept(see below);
Constraints: is_­move_­constructible_­v<T> is true and is_­move_­assignable_­v<T> is true.
Preconditions: Type T meets the Cpp17MoveConstructible (Table 28) and Cpp17MoveAssignable (Table 30) requirements.
Effects: Exchanges values stored in two locations.
Remarks: This function is a designated customization point ([namespace.std]).
The expression inside noexcept is equivalent to: is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>
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<T> 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).

20.2.3 exchange [utility.exchange]

template<class T, class U = T> constexpr T exchange(T& obj, U&& new_val);
Effects: Equivalent to: T old_val = std::move(obj); obj = std::forward<U>(new_val); return old_val;

20.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<T> is false.
Returns: static_­cast<T&&>(t).
[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.
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> constexpr remove_reference_t<T>&& move(T&& t) noexcept;
Returns: static_­cast<remove_­reference_­t<T>&&>(t).
[Example 2: 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> sp1 = 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.
This binds to the constructor A(const A&), which copies the value from a.
In the second call to factory, because of the call std​::​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).

20.2.5 Function template as_­const [utility.as.const]

template<class T> constexpr add_const_t<T>& as_const(T& t) noexcept;
Returns: t.

20.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<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.
For another example see class template common_­type ([meta.trans.other]).
— end example]

20.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<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; else return 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<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; else return 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<R>::min()) && cmp_less_equal(t, numeric_limits<R>::max());
[Note 1:
These function templates cannot be used to compare byte, char, char8_­t, char16_­t, char32_­t, wchar_­t, and bool.
— end note]

20.3 Compile-time integer sequences [intseq]

20.3.1 In general [intseq.general]

The library provides a class template that can represent an integer sequence.
When used as an argument to a function template the template parameter pack defining the sequence can be deduced and used in a pack expansion.
[Note 1:
The index_­sequence alias template is provided for the common case of an integer sequence of type size_­t; see also [tuple.apply].
— end note]

20.3.2 Class template integer_­sequence [intseq.intseq]

namespace std { template<class T, T... I> struct integer_sequence { using value_type = T; static constexpr size_t size() noexcept { return sizeof...(I); } }; }
Mandates: T is an integer type.

20.3.3 Alias template make_­integer_­sequence [intseq.make]

template<class T, T N> using make_integer_sequence = integer_sequence<T, see below>;
Mandates: .
The alias template make_­integer_­sequence denotes a specialization of integer_­sequence with N non-type template arguments.
The type make_­integer_­sequence<T, N> is an alias for the type integer_­sequence<T, 0, 1, ..., N-1>.
[Note 1:
make_­integer_­sequence<int, 0> is an alias for the type integer_­sequence<int>.
— end note]

20.4 Pairs [pairs]

20.4.1 In general [pairs.general]

The library provides a template for heterogeneous pairs of values.
The library also provides a matching function template to simplify their construction and several templates that provide access to pair objects as if they were tuple objects (see [tuple.helper] and [tuple.elem]).

20.4.2 Class template pair [pairs.pair]

namespace std { template<class T1, class T2> struct pair { using first_type = T1; using second_type = T2; T1 first; T2 second; pair(const pair&) = default; pair(pair&&) = default; constexpr explicit(see below) pair(); constexpr explicit(see below) pair(const T1& x, const T2& y); template<class U1, class U2> constexpr explicit(see below) pair(U1&& x, U2&& y); template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>& p); template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>&& p); template<class... Args1, class... Args2> constexpr pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args); constexpr pair& operator=(const pair& p); template<class U1, class U2> constexpr pair& operator=(const pair<U1, U2>& p); constexpr pair& operator=(pair&& p) noexcept(see below); template<class U1, class U2> constexpr pair& operator=(pair<U1, U2>&& p); constexpr void swap(pair& p) noexcept(see below); }; template<class T1, class T2> pair(T1, T2) -> pair<T1, T2>; }
Constructors and member functions of pair do not throw exceptions unless one of the element-wise operations specified to be called for that operation throws an exception.
The defaulted move and copy constructor, respectively, of pair is a constexpr function if and only if all required element-wise initializations for move and copy, respectively, would satisfy the requirements for a constexpr function.
If (is_­trivially_­destructible_­v<T1> && is_­trivially_­destructible_­v<T2>) is true, then the destructor of pair is trivial.
pair<T, U> is a structural type ([temp.param]) if T and U are both structural types.
Two values p1 and p2 of type pair<T, U> are template-argument-equivalent ([temp.type]) if and only if p1.first and p2.first are template-argument-equivalent and p1.second and p2.second are template-argument-equivalent.
constexpr explicit(see below) pair();
Constraints:
  • is_­default_­constructible_­v<first_­type> is true and
  • is_­default_­constructible_­v<second_­type> is true.
Effects: Value-initializes first and second.
Remarks: The expression inside explicit evaluates to true if and only if either first_­type or second_­type is not implicitly default-constructible.
[Note 1:
This behavior can be implemented with a trait that checks whether a const first_­type& or a const second_­type& can be initialized with {}.
— end note]
constexpr explicit(see below) pair(const T1& x, const T2& y);
Constraints:
  • is_­copy_­constructible_­v<first_­type> is true and
  • is_­copy_­constructible_­v<second_­type> is true.
Effects: Initializes first with x and second with y.
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<const first_type&, first_type> || !is_convertible_v<const second_type&, second_type>
template<class U1, class U2> constexpr explicit(see below) pair(U1&& x, U2&& y);
Constraints:
  • is_­constructible_­v<first_­type, U1> is true and
  • is_­constructible_­v<second_­type, U2> is true.
Effects: Initializes first with std​::​forward<U1>(x) and second with std​::​forward<U2>(y).
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>& p);
Constraints:
  • is_­constructible_­v<first_­type, const U1&> is true and
  • is_­constructible_­v<second_­type, const U2&> is true.
Effects: Initializes members from the corresponding members of the argument.
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<const U1&, first_type> || !is_convertible_v<const U2&, second_type>
template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>&& p);
Constraints:
  • is_­constructible_­v<first_­type, U1> is true and
  • is_­constructible_­v<second_­type, U2> is true.
Effects: Initializes first with std​::​forward<U1>(p.first) and second with std​::​forward<U2>(​p.second).
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
template<class... Args1, class... Args2> constexpr pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args);
Mandates:
  • is_­constructible_­v<first_­type, Args1...> is true and
  • is_­constructible_­v<second_­type, Args2...> is true.
Effects: Initializes first with arguments of types Args1... obtained by forwarding the elements of first_­args and initializes second with arguments of types Args2... obtained by forwarding the elements of second_­args.
(Here, forwarding an element x of type U within a tuple object means calling std​::​forward<U>(x).)
This form of construction, whereby constructor arguments for first and second are each provided in a separate tuple object, is called piecewise construction.
constexpr pair& operator=(const pair& p);
Effects: Assigns p.first to first and p.second to second.
Returns: *this.
Remarks: This operator is defined as deleted unless is_­copy_­assignable_­v<first_­type> is true and is_­copy_­assignable_­v<second_­type> is true.
template<class U1, class U2> constexpr pair& operator=(const pair<U1, U2>& p);
Constraints:
  • is_­assignable_­v<first_­type&, const U1&> is true and
  • is_­assignable_­v<second_­type&, const U2&> is true.
Effects: Assigns p.first to first and p.second to second.
Returns: *this.
constexpr pair& operator=(pair&& p) noexcept(see below);
Constraints:
  • is_­move_­assignable_­v<first_­type> is true and
  • is_­move_­assignable_­v<second_­type> is true.
Effects: Assigns to first with std​::​forward<first_­type>(p.first) and to second with
std​::​forward<second_­type>(p.second).
Returns: *this.
Remarks: The expression inside noexcept is equivalent to: is_nothrow_move_assignable_v<T1> && is_nothrow_move_assignable_v<T2>
template<class U1, class U2> constexpr pair& operator=(pair<U1, U2>&& p);
Constraints:
  • is_­assignable_­v<first_­type&, U1> is true and
  • is_­assignable_­v<second_­type&, U2> is true.
Effects: Assigns to first with std​::​forward<U1>(p.first) and to second with
std​::​forward<U2>(p.second).
Returns: *this.
constexpr void swap(pair& p) noexcept(see below);
Preconditions: first is swappable with ([swappable.requirements]) p.first and second is swappable with p.second.
Effects: Swaps first with p.first and second with p.second.
Remarks: The expression inside noexcept is equivalent to: is_nothrow_swappable_v<first_type> && is_nothrow_swappable_v<second_type>

20.4.3 Specialized algorithms [pairs.spec]

template<class T1, class T2> constexpr bool operator==(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: x.first == y.first && x.second == y.second.
template<class T1, class T2> constexpr common_comparison_category_t<synth-three-way-result<T1>, synth-three-way-result<T2>> operator<=>(const pair<T1, T2>& x, const pair<T1, T2>& y);
Effects: Equivalent to: if (auto c = synth-three-way(x.first, y.first); c != 0) return c; return synth-three-way(x.second, y.second);
template<class T1, class T2> constexpr void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_­swappable_­v<T1> is true and is_­swappable_­v<T2> is true.
Effects: Equivalent to x.swap(y).
template<class T1, class T2> constexpr pair<unwrap_ref_decay_t<T1>, unwrap_ref_decay_t<T2>> make_pair(T1&& x, T2&& y);
Returns: pair<unwrap_ref_decay_t<T1>, unwrap_ref_decay_t<T2>>(std::forward<T1>(x), std::forward<T2>(y))
[Example 1:
In place of: return pair<int, double>(5, 3.1415926); // explicit types a C++ program may contain: return make_pair(5, 3.1415926); // types are deduced
— end example]

20.4.4 Tuple-like access to pair [pair.astuple]

template<class T1, class T2> struct tuple_size<pair<T1, T2>> : integral_constant<size_t, 2> { };
template<size_t I, class T1, class T2> struct tuple_element<I, pair<T1, T2>> { using type = see below ; };
Mandates: .
Type: The type T1 if I is 0, otherwise the type T2.
template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>& p) noexcept; template<size_t I, class T1, class T2> constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>& p) noexcept; template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&& p) noexcept; template<size_t I, class T1, class T2> constexpr const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&& p) noexcept;
Mandates: .
Returns:
  • If I is 0, returns a reference to p.first.
  • If I is 1, returns a reference to p.second.
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;
Mandates: T1 and T2 are distinct types.
Returns: A reference to p.first.
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;
Mandates: T1 and T2 are distinct types.
Returns: A reference to p.second.

20.4.5 Piecewise construction [pair.piecewise]

struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; inline constexpr piecewise_construct_t piecewise_construct{};
The struct piecewise_­construct_­t is an empty class type used as a unique type to disambiguate constructor and function overloading.
Specifically, pair has a constructor with piecewise_­construct_­t as the first argument, immediately followed by two tuple arguments used for piecewise construction of the elements of the pair object.

20.5 Tuples [tuple]

20.5.1 In general [tuple.general]

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.
Each template argument specifies the type of an element in the tuple.
Consequently, tuples are heterogeneous, fixed-size collections of values.
An instantiation of tuple with two arguments is similar to an instantiation of pair with the same two arguments.

20.5.2 Header <tuple> synopsis [tuple.syn]

#include <compare> // see [compare.syn] namespace std { // [tuple.tuple], class template tuple template<class... Types> class tuple; // [tuple.creation], tuple creation functions inline constexpr unspecified ignore; template<class... TTypes> constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&...); template<class... TTypes> constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&...) noexcept; template<class... TTypes> constexpr tuple<TTypes&...> tie(TTypes&...) noexcept; template<class... Tuples> constexpr tuple<CTypes...> tuple_cat(Tuples&&...); // [tuple.apply], calling a function with a tuple of arguments template<class F, class Tuple> constexpr decltype(auto) apply(F&& f, Tuple&& t); template<class T, class Tuple> constexpr T make_from_tuple(Tuple&& t); // [tuple.helper], tuple helper classes template<class T> struct tuple_size; // not defined template<class T> struct tuple_size<const T>; template<class... Types> struct tuple_size<tuple<Types...>>; template<size_t I, class T> struct tuple_element; // not defined template<size_t I, class T> struct tuple_element<I, const T>; template<size_t I, class... Types> struct tuple_element<I, tuple<Types...>>; template<size_t I, class T> using tuple_element_t = typename tuple_element<I, T>::type; // [tuple.elem], element access template<size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>& get(tuple<Types...>&) noexcept; template<size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>&& get(tuple<Types...>&&) noexcept; template<size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>& get(const tuple<Types...>&) noexcept; template<size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&&) noexcept; template<class T, class... Types> constexpr T& get(tuple<Types...>& t) noexcept; template<class T, class... Types> constexpr T&& get(tuple<Types...>&& t) noexcept; template<class T, class... Types> constexpr const T& get(const tuple<Types...>& t) noexcept; template<class T, class... Types> constexpr const T&& get(const tuple<Types...>&& t) noexcept; // [tuple.rel], relational operators template<class... TTypes, class... UTypes> constexpr bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, class... UTypes> constexpr common_comparison_category_t<synth-three-way-result<TTypes, UTypes>...> operator<=>(const tuple<TTypes...>&, const tuple<UTypes...>&); // [tuple.traits], allocator-related traits template<class... Types, class Alloc> struct uses_allocator<tuple<Types...>, Alloc>; // [tuple.special], specialized algorithms template<class... Types> constexpr void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below); // [tuple.helper], tuple helper classes template<class T> inline constexpr size_t tuple_size_v = tuple_size<T>::value; }

20.5.3 Class template tuple [tuple.tuple]

namespace std { template<class... Types> class tuple { public: // [tuple.cnstr], tuple construction constexpr explicit(see below) tuple(); constexpr explicit(see below) tuple(const Types&...); // only if sizeof...(Types) >= 1 template<class... UTypes> constexpr explicit(see below) tuple(UTypes&&...); // only if sizeof...(Types) >= 1 tuple(const tuple&) = default; tuple(tuple&&) = default; template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>&); template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&&); template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>&); // only if sizeof...(Types) == 2 template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>&&); // only if sizeof...(Types) == 2 // allocator-extended constructors template<class Alloc> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a); template<class Alloc> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const Types&...); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTypes&&...); template<class Alloc> constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&); template<class Alloc> constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&); // [tuple.assign], tuple assignment constexpr tuple& operator=(const tuple&); constexpr tuple& operator=(tuple&&) noexcept(see below); template<class... UTypes> constexpr tuple& operator=(const tuple<UTypes...>&); template<class... UTypes> constexpr tuple& operator=(tuple<UTypes...>&&); template<class U1, class U2> constexpr tuple& operator=(const pair<U1, U2>&); // only if sizeof...(Types) == 2 template<class U1, class U2> constexpr tuple& operator=(pair<U1, U2>&&); // only if sizeof...(Types) == 2 // [tuple.swap], tuple swap constexpr void swap(tuple&) noexcept(see below); }; template<class... UTypes> tuple(UTypes...) -> tuple<UTypes...>; template<class T1, class T2> tuple(pair<T1, T2>) -> tuple<T1, T2>; template<class Alloc, class... UTypes> tuple(allocator_arg_t, Alloc, UTypes...) -> tuple<UTypes...>; template<class Alloc, class T1, class T2> tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>; template<class Alloc, class... UTypes> tuple(allocator_arg_t, Alloc, tuple<UTypes...>) -> tuple<UTypes...>; }

20.5.3.1 Construction [tuple.cnstr]

In the descriptions that follow, let i be in the range [0, sizeof...(Types)) in order, be the type in Types, and be the type in a template parameter pack named UTypes, where indexing is zero-based.
For each tuple constructor, an exception is thrown only if the construction of one of the types in Types throws an exception.
The defaulted move and copy constructor, respectively, of tuple is a constexpr function if and only if all required element-wise initializations for move and copy, respectively, would satisfy the requirements for a constexpr function.
The defaulted move and copy constructor of tuple<> are constexpr functions.
If is_­trivially_­destructible_­v<> is true for all , then the destructor of tuple is trivial.
constexpr explicit(see below) tuple();
Constraints: is_­default_­constructible_­v<> is true for all i.
Effects: Value-initializes each element.
Remarks: The expression inside explicit evaluates to true if and only if is not copy-list-initializable from an empty list for at least one i.
[Note 1:
This behavior can be implemented with a trait that checks whether a const & can be initialized with {}.
— end note]
constexpr explicit(see below) tuple(const Types&...);
Constraints: and is_­copy_­constructible_­v<> is true for all i.
Effects: Initializes each element with the value of the corresponding parameter.
Remarks: The expression inside explicit is equivalent to: !conjunction_v<is_convertible<const Types&, Types>...>
template<class... UTypes> constexpr explicit(see below) tuple(UTypes&&... u);
Constraints: sizeof...(Types) equals sizeof...(UTypes) and and is_­constructible_­v<, > is true for all i.
Effects: Initializes the elements in the tuple with the corresponding value in std​::​forward<UTypes>(u).
Remarks: The expression inside explicit is equivalent to: !conjunction_v<is_convertible<UTypes, Types>...>
tuple(const tuple& u) = default;
Mandates: is_­copy_­constructible_­v<> is true for all i.
Effects: Initializes each element of *this with the corresponding element of u.
tuple(tuple&& u) = default;
Constraints: is_­move_­constructible_­v<> is true for all i.
Effects: For all i, initializes the element of *this with std​::​forward<>(get<i>(u)).
template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>& u);
Constraints:
  • sizeof...(Types) equals sizeof...(UTypes) and
  • is_­constructible_­v<, const &> is true for all i, and
  • either sizeof...(Types) is not 1, or (when Types... expands to T and UTypes... expands to U) is_­convertible_­v<const tuple<U>&, T>, is_­constructible_­v<T, const tuple<U>&>, and is_­same_­v<T, U> are all false.
Effects: Initializes each element of *this with the corresponding element of u.
Remarks: The expression inside explicit is equivalent to: !conjunction_v<is_convertible<const UTypes&, Types>...>
template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&& u);
Constraints:
  • sizeof...(Types) equals sizeof...(UTypes), and
  • is_­constructible_­v<, > is true for all i, and
  • either sizeof...(Types) is not 1, or (when Types... expands to T and UTypes... expands to U) is_­convertible_­v<tuple<U>, T>, is_­constructible_­v<T, tuple<U>>, and is_­same_­v<T, U> are all false.
Effects: For all i, initializes the element of *this with std​::​forward<>(get<i>(u)).
Remarks: The expression inside explicit is equivalent to: !conjunction_v<is_convertible<UTypes, Types>...>
template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>& u);
Constraints:
  • sizeof...(Types) is 2,
  • is_­constructible_­v<, const U1&> is true, and
  • is_­constructible_­v<, const U2&> is true.
Effects: Initializes the first element with u.first and the second element with u.second.
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<const U1&, > || !is_convertible_v<const U2&, >
template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>&& u);
Constraints:
  • sizeof...(Types) is 2,
  • is_­constructible_­v<, U1> is true, and
  • is_­constructible_­v<, U2> is true.
Effects: Initializes the first element with std​::​forward<U1>(u.first) and the second element with std​::​forward<U2>(u.second).
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<U1, > || !is_convertible_v<U2, >
template<class Alloc> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a); template<class Alloc> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const Types&...); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTypes&&...); template<class Alloc> constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&); template<class Alloc> constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
Preconditions: Alloc meets the Cpp17Allocator requirements (Table 36).
Effects: Equivalent to the preceding constructors except that each element is constructed with uses-allocator construction.

20.5.3.2 Assignment [tuple.assign]

For each tuple assignment operator, an exception is thrown only if the assignment of one of the types in Types throws an exception.
In the function descriptions that follow, let i be in the range [0, sizeof...(Types)) in order, be the type in Types, and be the type in a template parameter pack named UTypes, where indexing is zero-based.
constexpr tuple& operator=(const tuple& u);
Effects: Assigns each element of u to the corresponding element of *this.
Returns: *this.
Remarks: This operator is defined as deleted unless is_­copy_­assignable_­v<> is true for all i.
constexpr tuple& operator=(tuple&& u) noexcept(see below);
Constraints: is_­move_­assignable_­v<> is true for all i.
Effects: For all i, assigns std​::​forward<>(get<i>(u)) to get<i>(*this).
Returns: *this.
Remarks: The expression inside noexcept is equivalent to the logical AND of the following expressions: is_nothrow_move_assignable_v<> where is the type in Types.
template<class... UTypes> constexpr tuple& operator=(const tuple<UTypes...>& u);
Constraints:
  • sizeof...(Types) equals sizeof...(UTypes) and
  • is_­assignable_­v<&, const &> is true for all i.
Effects: Assigns each element of u to the corresponding element of *this.
Returns: *this.
template<class... UTypes> constexpr tuple& operator=(tuple<UTypes...>&& u);
Constraints:
  • sizeof...(Types) equals sizeof...(UTypes) and
  • is_­assignable_­v<&, > is true for all i.
Effects: For all i, assigns std​::​forward<>(get<i>(u)) to get<i>(*this).
Returns: *this.
template<class U1, class U2> constexpr tuple& operator=(const pair<U1, U2>& u);
Constraints:
  • sizeof...(Types) is 2 and
  • is_­assignable_­v<&, const U1&> is true, and
  • is_­assignable_­v<&, const U2&> is true.
Effects: Assigns u.first to the first element of *this and u.second to the second element of *this.
Returns: *this.
template<class U1, class U2> constexpr tuple& operator=(pair<U1, U2>&& u);
Constraints:
  • sizeof...(Types) is 2 and
  • is_­assignable_­v<&, U1> is true, and
  • is_­assignable_­v<&, U2> is true.
Effects: Assigns std​::​forward<U1>(u.first) to the first element of *this and
std​::​forward<U2>(u.second) to the second element of *this.
Returns: *this.

20.5.3.3 swap [tuple.swap]

constexpr void swap(tuple& rhs) noexcept(see below);
Preconditions: Each element in *this is swappable with ([swappable.requirements]) the corresponding element in rhs.
Effects: Calls swap for each element in *this and its corresponding element in rhs.
Throws: Nothing unless one of the element-wise swap calls throws an exception.
Remarks: The expression inside noexcept is equivalent to the logical AND of the following expressions: is_nothrow_swappable_v<> where is the type in Types.

20.5.4 Tuple creation functions [tuple.creation]

In the function descriptions that follow, the members of a template parameter pack XTypes are denoted by X for i in [0, sizeof...(XTypes)) in order, where indexing is zero-based.
template<class... TTypes> constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&... t);
Returns: tuple<unwrap_­ref_­decay_­t<TTypes>...>(std​::​forward<TTypes>(t)...).
[Example 1:
int i; float j; make_tuple(1, ref(i), cref(j)) creates a tuple of type tuple<int, int&, const float&>.
— end example]
template<class... TTypes> constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&... t) noexcept;
Effects: Constructs a tuple of references to the arguments in t suitable for forwarding as arguments to a function.
Because the result may contain references to temporary 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).
Returns: tuple<TTypes&&...>(std​::​forward<TTypes>(t)...).
template<class... TTypes> constexpr tuple<TTypes&...> tie(TTypes&... t) noexcept;
Returns: tuple<TTypes&...>(t...).
When an argument in t is ignore, assigning any value to the corresponding tuple element has no effect.
[Example 2:
tie functions allow one to create tuples that unpack tuples into variables.
ignore can be used for elements that are not needed: int i; std::string s; tie(i, ignore, s) = make_tuple(42, 3.14, "C++"); // i == 42, s == "C++"
— end example]
template<class... Tuples> constexpr tuple<CTypes...> tuple_cat(Tuples&&... tpls);
In the following paragraphs, let be the type in Tuples, be remove_­reference_­t<T>, and be the parameter in the function parameter pack tpls, where all indexing is zero-based.
Preconditions: For all i, is the type tuple<...>, where is the (possibly empty) cv-qualifier-seq and is the template parameter pack representing the element types in .
Let be the type in .
For all the following requirements are met:
  • If is deduced as an lvalue reference type, then is_­constructible_­v<, &> == true, otherwise
  • is_­constructible_­v<, &&> == true.
Remarks: The types in CTypes are equal to the ordered sequence of the extended types ..., ..., , ..., where n is equal to sizeof...(Tuples).
Let ... be the ordered sequence of tuple elements of the resulting tuple object corresponding to the type sequence .
Returns: A tuple object constructed by initializing the type element in ... with get<>(std::forward<>()) for each valid and each group in order.
[Note 1:
An implementation can support additional types in the template parameter pack Tuples that support the tuple-like protocol, such as pair and array.
— end note]

20.5.5 Calling a function with a tuple of arguments [tuple.apply]

template<class F, class Tuple> constexpr decltype(auto) apply(F&& f, Tuple&& t);
Effects: Given the exposition-only function: template<class F, class Tuple, size_t... I> constexpr decltype(auto) apply-impl(F&& f, Tuple&& t, index_sequence<I...>) { // exposition only return INVOKE(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...); // see [func.require] }
Equivalent to: return apply-impl(std::forward<F>(f), std::forward<Tuple>(t), make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
template<class T, class Tuple> constexpr T make_from_tuple(Tuple&& t);
Effects: Given the exposition-only function: template<class T, class Tuple, size_t... I> constexpr T make-from-tuple-impl(Tuple&& t, index_sequence<I...>) { // exposition only return T(get<I>(std::forward<Tuple>(t))...); }
Equivalent to: return make-from-tuple-impl<T>( forward<Tuple>(t), make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
[Note 1:
The type of T must be supplied as an explicit template parameter, as it cannot be deduced from the argument list.
— end note]

20.5.6 Tuple helper classes [tuple.helper]

template<class T> struct tuple_size;
All specializations of tuple_­size meet the Cpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_­constant<size_­t, N> for some N.
template<class... Types> struct tuple_size<tuple<Types...>> : public integral_constant<size_t, sizeof...(Types)> { };
template<size_t I, class... Types> struct tuple_element<I, tuple<Types...>> { using type = TI; };
Mandates: .
Type: TI is the type of the element of Types, where indexing is zero-based.
template<class T> struct tuple_size<const T>;
Let TS denote tuple_­size<T> of the cv-unqualified type T.
If the expression TS​::​value is well-formed when treated as an unevaluated operand, then each specialization of the template meets the Cpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_constant<size_t, TS::value>
Otherwise, it has no member value.
Access checking is performed as if in a context unrelated to TS and T.
Only the validity of the immediate context of the expression is considered.
[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.
Such side effects are not in the “immediate context” and can result in the program being ill-formed.
— end note]
In addition to being available via inclusion of the <tuple> header, the template is available when any of the headers <array>, <ranges>, or <utility> are included.
template<size_t I, class T> struct tuple_element<I, const T>;
Let TE denote tuple_­element_­t<I, T> of the cv-unqualified type T.
Then each specialization of the template meets the Cpp17TransformationTrait requirements ([meta.rqmts]) with a member typedef type that names the type add_­const_­t<TE>.
In addition to being available via inclusion of the <tuple> header, the template is available when any of the headers <array>, <ranges>, or <utility> are included.

20.5.7 Element access [tuple.elem]

template<size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>& get(tuple<Types...>& t) noexcept; template<size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>&& get(tuple<Types...>&& t) noexcept; // Note A template<size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>& get(const tuple<Types...>& t) noexcept; // Note B template<size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
Mandates: .
Returns: A reference to the element of t, where indexing is zero-based.
[Note A 1:
If a type T in Types is some reference type X&, the return type is X&, not X&&.
However, if the element type is a non-reference type T, the return type is T&&.
— end note]
[Note B 2:
Constness is shallow.
If a type T in Types is some reference type X&, the return type is X&, not const X&.
However, if the element type is a non-reference type T, the return type is const T&.
This is consistent with how constness is defined to work for member variables of reference type.
— end note]
template<class T, class... Types> constexpr T& get(tuple<Types...>& t) noexcept; template<class T, class... Types> constexpr T&& get(tuple<Types...>&& t) noexcept; template<class T, class... Types> constexpr const T& get(const tuple<Types...>& t) noexcept; template<class T, class... Types> constexpr const T&& get(const tuple<Types...>&& t) noexcept;
Mandates: The type T occurs exactly once in Types.
Returns: A reference to the element of t corresponding to the type T in Types.
[Example 1: const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6); const int& i1 = get<int>(t); // OK, i1 has value 1 const int& i2 = get<const int>(t); // OK, i2 has value 2 const double& d = get<double>(t); // error: type double is not unique within t — end example]
[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.
— end note]

20.5.8 Relational operators [tuple.rel]

template<class... TTypes, class... UTypes> constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Mandates: For all i, where , get<i>(t) == get<i>(u) is a valid expression returning a type that is convertible to bool.
sizeof...(TTypes) equals sizeof...(UTypes).
Returns: true if get<i>(t) == get<i>(u) for all i, otherwise false.
For any two zero-length tuples e and f, e == f returns true.
Remarks: The elementary comparisons are performed in order from the zeroth index upwards.
No comparisons or element accesses are performed after the first equality comparison that evaluates to false.
template<class... TTypes, class... UTypes> constexpr common_comparison_category_t<synth-three-way-result<TTypes, UTypes>...> operator<=>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Effects: Performs a lexicographical comparison between t and u.
For any two zero-length tuples t and u, t <=> u returns strong_­ordering​::​equal.
Otherwise, equivalent to: if (auto c = synth-three-way(get<0>(t), get<0>(u)); c != 0) return c; return <=> ; where for some tuple r is a tuple containing all but the first element of r.
[Note 1:
The above definition does not require t (or u) to be constructed.
It might not even be possible, as t and u are not required to be copy constructible.
Also, all comparison operator functions are short circuited; they do not perform element accesses beyond what is required to determine the result of the comparison.
— end note]

20.5.9 Tuple traits [tuple.traits]

template<class... Types, class Alloc> struct uses_allocator<tuple<Types...>, Alloc> : true_type { };
Preconditions: Alloc meets the Cpp17Allocator requirements (Table 36).
[Note 1:
Specialization of this trait informs other library components that tuple can be constructed with an allocator, even though it does not have a nested allocator_­type.
— end note]

20.5.10 Tuple specialized algorithms [tuple.special]

template<class... Types> constexpr void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
Constraints: is_­swappable_­v<T> is true for every type T in Types.
Effects: As if by x.swap(y).
Remarks: The expression inside noexcept is equivalent to: noexcept(x.swap(y))

20.6 Optional objects [optional]

20.6.1 In general [optional.general]

Subclause [optional] describes class template optional that represents optional objects.
An optional object is an object that contains the storage for another object and manages the lifetime of this contained object, if any.
The contained object may be initialized after the optional object has been initialized, and may be destroyed before the optional object has been destroyed.
The initialization state of the contained object is tracked by the optional object.

20.6.2 Header <optional> synopsis [optional.syn]

#include <compare> // see [compare.syn] namespace std { // [optional.optional], class template optional template<class T> class optional; // [optional.nullopt], no-value state indicator struct nullopt_t{see below}; inline constexpr nullopt_t nullopt(unspecified); // [optional.bad.access], class bad_­optional_­access class bad_optional_access; // [optional.relops], relational operators template<class T, class U> constexpr bool operator==(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator!=(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator<(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator>(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator<=(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator>=(const optional<T>&, const optional<U>&); template<class T, three_­way_­comparable_­with<T> U> constexpr compare_three_way_result_t<T,U> operator<=>(const optional<T>&, const optional<U>&); // [optional.nullops], comparison with nullopt template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; template<class T> constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept; // [optional.comp.with.t], comparison with T template<class T, class U> constexpr bool operator==(const optional<T>&, const U&); template<class T, class U> constexpr bool operator==(const T&, const optional<U>&); template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&); template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&); template<class T, class U> constexpr bool operator<(const optional<T>&, const U&); template<class T, class U> constexpr bool operator<(const T&, const optional<U>&); template<class T, class U> constexpr bool operator>(const optional<T>&, const U&); template<class T, class U> constexpr bool operator>(const T&, const optional<U>&); template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&); template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&); template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&); template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&); template<class T, three_­way_­comparable_­with<T> U> constexpr compare_three_way_result_t<T,U> operator<=>(const optional<T>&, const U&); // [optional.specalg], specialized algorithms template<class T> void swap(optional<T>&, optional<T>&) noexcept(see below); template<class T> constexpr optional<see below> make_optional(T&&); template<class T, class... Args> constexpr optional<T> make_optional(Args&&... args); template<class T, class U, class... Args> constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); // [optional.hash], hash support template<class T> struct hash; template<class T> struct hash<optional<T>>; }

20.6.3 Class template optional [optional.optional]

20.6.3.1 General [optional.optional.general]

namespace std { template<class T> class optional { public: using value_type = T; // [optional.ctor], constructors constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept; constexpr optional(const optional&); constexpr optional(optional&&) noexcept(see below); template<class... Args> constexpr explicit optional(in_place_t, Args&&...); template<class U, class... Args> constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...); template<class U = T> constexpr explicit(see below) optional(U&&); template<class U> explicit(see below) optional(const optional<U>&); template<class U> explicit(see below) optional(optional<U>&&); // [optional.dtor], destructor ~optional(); // [optional.assign], assignment optional& operator=(nullopt_t) noexcept; constexpr optional& operator=(const optional&); constexpr optional& operator=(optional&&) noexcept(see below); template<class U = T> optional& operator=(U&&); template<class U> optional& operator=(const optional<U>&); template<class U> optional& operator=(optional<U>&&); template<class... Args> T& emplace(Args&&...); template<class U, class... Args> T& emplace(initializer_list<U>, Args&&...); // [optional.swap], swap void swap(optional&) noexcept(see below); // [optional.observe], observers constexpr const T* operator->() const; constexpr T* operator->(); constexpr const T& operator*() const&; constexpr T& operator*() &; constexpr T&& operator*() &&; constexpr const T&& operator*() const&&; constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; constexpr const T& value() const&; constexpr T& value() &; constexpr T&& value() &&; constexpr const T&& value() const&&; template<class U> constexpr T value_or(U&&) const&; template<class U> constexpr T value_or(U&&) &&; // [optional.mod], modifiers void reset() noexcept; private: T *val; // exposition only }; template<class T> optional(T) -> optional<T>; }
Any instance of optional<T> at any given time either contains a value or does not contain a value.
When an instance of optional<T> contains a value, it means that an object of type T, referred to as the optional object's contained value, is allocated within the storage of the optional object.
Implementations are not permitted to use additional storage, such as dynamic memory, to allocate its contained value.
The contained value shall be allocated in a region of the optional<T> storage suitably aligned for the type T.
When an object of type optional<T> is contextually converted to bool, the conversion returns true if the object contains a value; otherwise the conversion returns false.
Member val is provided for exposition only.
When an optional<T> object contains a value, val points to the contained value.
T shall be a type other than cv in_­place_­t or cv nullopt_­t that meets the Cpp17Destructible requirements (Table 32).

20.6.3.2 Constructors [optional.ctor]

constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept;
Postconditions: *this does not contain a value.
Remarks: No contained value is initialized.
For every object type T these constructors are constexpr constructors ([dcl.constexpr]).
constexpr optional(const optional& rhs);
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object of type T with the expression *rhs.
Postconditions: bool(rhs) == bool(*this).
Throws: Any exception thrown by the selected constructor of T.
Remarks: This constructor is defined as deleted unless is_­copy_­constructible_­v<T> is true.
If is_­trivially_­copy_­constructible_­v<T> is true, this constructor is trivial.
constexpr optional(optional&& rhs) noexcept(see below);
Constraints: is_­move_­constructible_­v<T> is true.
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object of type T with the expression std​::​move(*rhs).
bool(rhs) is unchanged.
Postconditions: bool(rhs) == bool(*this).
Throws: Any exception thrown by the selected constructor of T.
Remarks: The expression inside noexcept is equivalent to is_­nothrow_­move_­constructible_­v<T>.
If is_­trivially_­move_­constructible_­v<T> is true, this constructor is trivial.
template<class... Args> constexpr explicit optional(in_place_t, Args&&... args);
Constraints: is_­constructible_­v<T, Args...> is true.
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std​::​forward<Args>(args)....
Postconditions: *this contains a value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If T's constructor selected for the initialization is a constexpr constructor, this constructor is a constexpr constructor.
template<class U, class... Args> constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);
Constraints: is_­constructible_­v<T, initializer_­list<U>&, Args...> is true.
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std​::​forward<Args>(args)....
Postconditions: *this contains a value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If T's constructor selected for the initialization is a constexpr constructor, this constructor is a constexpr constructor.
template<class U = T> constexpr explicit(see below) optional(U&& v);
Constraints: is_­constructible_­v<T, U> is true, is_­same_­v<remove_­cvref_­t<U>, in_­place_­t> is false, and is_­same_­v<remove_­cvref_­t<U>, optional> is false.
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the expression std​::​forward<U>(v).
Postconditions: *this contains a value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
The expression inside explicit is equivalent to: !is_convertible_v<U, T>
template<class U> explicit(see below) optional(const optional<U>& rhs);
Constraints:
  • is_­constructible_­v<T, const U&> is true,
  • is_­constructible_­v<T, optional<U>&> is false,
  • is_­constructible_­v<T, optional<U>&&> is false,
  • is_­constructible_­v<T, const optional<U>&> is false,
  • is_­constructible_­v<T, const optional<U>&&> is false,
  • is_­convertible_­v<optional<U>&, T> is false,
  • is_­convertible_­v<optional<U>&&, T> is false,
  • is_­convertible_­v<const optional<U>&, T> is false, and
  • is_­convertible_­v<const optional<U>&&, T> is false.
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object of type T with the expression *rhs.
Postconditions: bool(rhs) == bool(*this).
Throws: Any exception thrown by the selected constructor of T.
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<const U&, T>
template<class U> explicit(see below) optional(optional<U>&& rhs);
Constraints:
  • is_­constructible_­v<T, U> is true,
  • is_­constructible_­v<T, optional<U>&> is false,
  • is_­constructible_­v<T, optional<U>&&> is false,
  • is_­constructible_­v<T, const optional<U>&> is false,
  • is_­constructible_­v<T, const optional<U>&&> is false,
  • is_­convertible_­v<optional<U>&, T> is false,
  • is_­convertible_­v<optional<U>&&, T> is false,
  • is_­convertible_­v<const optional<U>&, T> is false, and
  • is_­convertible_­v<const optional<U>&&, T> is false.
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object of type T with the expression std​::​move(*rhs).
bool(rhs) is unchanged.
Postconditions: bool(rhs) == bool(*this).
Throws: Any exception thrown by the selected constructor of T.
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<U, T>

20.6.3.3 Destructor [optional.dtor]

~optional();
Effects: If is_­trivially_­destructible_­v<T> != true and *this contains a value, calls val->T::~T()
Remarks: If is_­trivially_­destructible_­v<T> is true, then this destructor is trivial.

20.6.3.4 Assignment [optional.assign]

optional<T>& operator=(nullopt_t) noexcept;
Effects: If *this contains a value, calls val->T​::​~T() to destroy the contained value; otherwise no effect.
Postconditions: *this does not contain a value.
Returns: *this.
constexpr optional<T>& operator=(const optional& rhs);
Effects: See Table 42.
Table 42: optional​::​operator=(const optional&) effects [tab:optional.assign.copy]
*this contains a value
*this does not contain a value
rhs contains a value
assigns *rhs to the contained value
initializes the contained value as if direct-non-list-initializing an object of type T with *rhs
rhs does not contain a value
destroys the contained value by calling val->T​::​~T()
no effect
Postconditions: bool(rhs) == bool(*this).
Returns: *this.
Remarks: If any exception is thrown, the result of the expression bool(*this) remains unchanged.
If an exception is thrown during the call to T's copy constructor, no effect.
If an exception is thrown during the call to T's copy assignment, the state of its contained value is as defined by the exception safety guarantee of T's copy assignment.
This operator is defined as deleted unless is_­copy_­constructible_­v<T> is true and is_­copy_­assignable_­v<T> is true.
If is_­trivially_­copy_­constructible_­v<T> && is_­trivially_­copy_­assignable_­v<T> && is_­trivially_­destructible_­v<T> is true, this assignment operator is trivial.
constexpr optional& operator=(optional&& rhs) noexcept(see below);
Constraints: is_­move_­constructible_­v<T> is true and is_­move_­assignable_­v<T> is true.
Effects: See Table 43.
The result of the expression bool(rhs) remains unchanged.
Table 43: optional​::​operator=(optional&&) effects [tab:optional.assign.move]
*this contains a value
*this does not contain a value
rhs contains a value
assigns std​::​move(*rhs) to the contained value
initializes the contained value as if direct-non-list-initializing an object of type T with std​::​move(*rhs)
rhs does not contain a value
destroys the contained value by calling val->T​::​~T()
no effect
Postconditions: bool(rhs) == bool(*this).
Returns: *this.
Remarks: The expression inside noexcept is equivalent to: is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T>
If any exception is thrown, the result of the expression bool(*this) remains unchanged.
If an exception is thrown during the call to T's move constructor, the state of *rhs.val is determined by the exception safety guarantee of T's move constructor.
If an exception is thrown during the call to T's move assignment, the state of *val and *rhs.val is determined by the exception safety guarantee of T's move assignment.
If is_­trivially_­move_­constructible_­v<T> && is_­trivially_­move_­assignable_­v<T> && is_­trivially_­destructible_­v<T> is true, this assignment operator is trivial.
template<class U = T> optional<T>& operator=(U&& v);
Constraints: is_­same_­v<remove_­cvref_­t<U>, optional> is false, conjunction_­v<is_­scalar<T>, is_­same<T, decay_­t<U>>> is false, is_­constructible_­v<T, U> is true, and is_­assignable_­v<T&, U> is true.
Effects: If *this contains a value, assigns std​::​forward<U>(v) to the contained value; otherwise initializes the contained value as if direct-non-list-initializing object of type T with std​::​forward<U>(v).
Postconditions: *this contains a value.
Returns: *this.
Remarks: If any exception is thrown, the result of the expression bool(*this) remains unchanged.
If an exception is thrown during the call to T's constructor, the state of v is determined by the exception safety guarantee of T's constructor.
If an exception is thrown during the call to T's assignment, the state of *val and v is determined by the exception safety guarantee of T's assignment.
template<class U> optional<T>& operator=(const optional<U>& rhs);
Constraints:
  • is_­constructible_­v<T, const U&> is true,
  • is_­assignable_­v<T&, const U&> is true,
  • is_­constructible_­v<T, optional<U>&> is false,
  • is_­constructible_­v<T, optional<U>&&> is false,
  • is_­constructible_­v<T, const optional<U>&> is false,
  • is_­constructible_­v<T, const optional<U>&&> is false,
  • is_­convertible_­v<optional<U>&, T> is false,
  • is_­convertible_­v<optional<U>&&, T> is false,
  • is_­convertible_­v<const optional<U>&, T> is false,
  • is_­convertible_­v<const optional<U>&&, T> is false,
  • is_­assignable_­v<T&, optional<U>&> is false,
  • is_­assignable_­v<T&, optional<U>&&> is false,
  • is_­assignable_­v<T&, const optional<U>&> is false, and
  • is_­assignable_­v<T&, const optional<U>&&> is false.
Effects: See Table 44.
Table 44: optional​::​operator=(const optional<U>&) effects [tab:optional.assign.copy.templ]
*this contains a value
*this does not contain a value
rhs contains a value
assigns *rhs to the contained value
initializes the contained value as if direct-non-list-initializing an object of type T with *rhs
rhs does not contain a value
destroys the contained value by calling val->T​::​~T()
no effect
Postconditions: bool(rhs) == bool(*this).
Returns: *this.
Remarks: If any exception is thrown, the result of the expression bool(*this) remains unchanged.
If an exception is thrown during the call to T's constructor, the state of *rhs.val is determined by the exception safety guarantee of T's constructor.
If an exception is thrown during the call to T's assignment, the state of *val and *rhs.val is determined by the exception safety guarantee of T's assignment.
template<class U> optional<T>& operator=(optional<U>&& rhs);
Constraints:
  • is_­constructible_­v<T, U> is true,
  • is_­assignable_­v<T&, U> is true,
  • is_­constructible_­v<T, optional<U>&> is false,
  • is_­constructible_­v<T, optional<U>&&> is false,
  • is_­constructible_­v<T, const optional<U>&> is false,
  • is_­constructible_­v<T, const optional<U>&&> is false,
  • is_­convertible_­v<optional<U>&, T> is false,
  • is_­convertible_­v<optional<U>&&, T> is false,
  • is_­convertible_­v<const optional<U>&, T> is false,
  • is_­convertible_­v<const optional<U>&&, T> is false,
  • is_­assignable_­v<T&, optional<U>&> is false,
  • is_­assignable_­v<T&, optional<U>&&> is false,
  • is_­assignable_­v<T&, const optional<U>&> is false, and
  • is_­assignable_­v<T&, const optional<U>&&> is false.
Effects: See Table 45.
The result of the expression bool(rhs) remains unchanged.
Table 45: optional​::​operator=(optional<U>&&) effects [tab:optional.assign.move.templ]
*this contains a value
*this does not contain a value
rhs contains a value
assigns std​::​move(*rhs) to the contained value
initializes the contained value as if direct-non-list-initializing an object of type T with std​::​move(*rhs)
rhs does not contain a value
destroys the contained value by calling val->T​::​~T()
no effect
Postconditions: bool(rhs) == bool(*this).
Returns: *this.
Remarks: If any exception is thrown, the result of the expression bool(*this) remains unchanged.
If an exception is thrown during the call to T's constructor, the state of *rhs.val is determined by the exception safety guarantee of T's constructor.
If an exception is thrown during the call to T's assignment, the state of *val and *rhs.val is determined by the exception safety guarantee of T's assignment.
template<class... Args> T& emplace(Args&&... args);
Mandates: is_­constructible_­v<T, Args...> is true.
Effects: Calls *this = nullopt.
Then initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std​::​forward<Args>(args)....
Postconditions: *this contains a value.
Returns: A reference to the new contained value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and the previous *val (if any) has been destroyed.
template<class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);
Constraints: is_­constructible_­v<T, initializer_­list<U>&, Args...> is true.
Effects: Calls *this = nullopt.
Then initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std​::​forward<Args>(args)....
Postconditions: *this contains a value.
Returns: A reference to the new contained value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and the previous *val (if any) has been destroyed.

20.6.3.5 Swap [optional.swap]

void swap(optional& rhs) noexcept(see below);
Mandates: is_­move_­constructible_­v<T> is true.
Preconditions: Lvalues of type T are swappable.
Effects: See Table 46.
Table 46: optional​::​swap(optional&) effects [tab:optional.swap]
*this contains a value
*this does not contain a value
rhs contains a value
calls swap(*(*this), *rhs)
initializes the contained value of *this as if direct-non-list-initializing an object of type T with the expression std​::​move(*rhs), followed by rhs.val->T​::​~T(); postcondition is that *this contains a value and rhs does not contain a value
rhs does not contain a value
initializes the contained value of rhs as if direct-non-list-initializing an object of type T with the expression std​::​move(*(*this)), followed by val->T​::​~T(); postcondition is that *this does not contain a value and rhs contains a value
no effect
Throws: Any exceptions thrown by the operations in the relevant part of Table 46.
Remarks: The expression inside noexcept is equivalent to: is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T>
If any exception is thrown, the results of the expressions bool(*this) and bool(rhs) remain unchanged.
If an exception is thrown during the call to function swap, the state of *val and *rhs.val is determined by the exception safety guarantee of swap for lvalues of T.
If an exception is thrown during the call to T's move constructor, the state of *val and *rhs.val is determined by the exception safety guarantee of T's move constructor.

20.6.3.6 Observers [optional.observe]

constexpr const T* operator->() const; constexpr T* operator->();
Preconditions: *this contains a value.
Returns: val.
Throws: Nothing.
Remarks: These functions are constexpr functions.
constexpr const T& operator*() const&; constexpr T& operator*() &;
Preconditions: *this contains a value.
Returns: *val.
Throws: Nothing.
Remarks: These functions are constexpr functions.
constexpr T&& operator*() &&; constexpr const T&& operator*() const&&;
Preconditions: *this contains a value.
Effects: Equivalent to: return std​::​move(*val);
constexpr explicit operator bool() const noexcept;
Returns: true if and only if *this contains a value.
Remarks: This function is a constexpr function.
constexpr bool has_value() const noexcept;
Returns: true if and only if *this contains a value.
Remarks: This function is a constexpr function.
constexpr const T& value() const&; constexpr T& value() &;
Effects: Equivalent to: return bool(*this) ? *val : throw bad_optional_access();
constexpr T&& value() &&; constexpr const T&& value() const&&;
Effects: Equivalent to: return bool(*this) ? std::move(*val) : throw bad_optional_access();
template<class U> constexpr T value_or(U&& v) const&;
Mandates: is_­copy_­constructible_­v<T> && is_­convertible_­v<U&&, T> is true.
Effects: Equivalent to: return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
template<class U> constexpr T value_or(U&& v) &&;
Mandates: is_­move_­constructible_­v<T> && is_­convertible_­v<U&&, T> is true.
Effects: Equivalent to: return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));

20.6.3.7 Modifiers [optional.mod]

void reset() noexcept;
Effects: If *this contains a value, calls val->T​::​~T() to destroy the contained value; otherwise no effect.
Postconditions: *this does not contain a value.

20.6.4 No-value state indicator [optional.nullopt]

struct nullopt_t{see below}; inline constexpr nullopt_t nullopt(unspecified);
The struct nullopt_­t is an empty class type used as a unique type to indicate the state of not containing a value for optional objects.
In particular, optional<T> has a constructor with nullopt_­t as a single argument; this indicates that an optional object not containing a value shall be constructed.
Type nullopt_­t shall not have a default constructor or an initializer-list constructor, and shall not be an aggregate.

20.6.5 Class bad_­optional_­access [optional.bad.access]

class bad_optional_access : public exception { public: // see [exception] for the specification of the special member functions const char* what() const noexcept override; };
The class bad_­optional_­access defines the type of objects thrown as exceptions to report the situation where an attempt is made to access the value of an optional object that does not contain a value.
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

20.6.6 Relational operators [optional.relops]

template<class T, class U> constexpr bool operator==(const optional<T>& x, const optional<U>& y);
Mandates: The expression *x == *y is well-formed and its result is convertible to bool.
[Note 1:
T need not be Cpp17EqualityComparable.
— end note]
Returns: If bool(x) != bool(y), false; otherwise if bool(x) == false, true; otherwise *x == *y.
Remarks: Specializations of this function template for which *x == *y is a core constant expression are constexpr functions.
template<class T, class U> constexpr bool operator!=(const optional<T>& x, const optional<U>& y);
Mandates: The expression *x != *y is well-formed and its result is convertible to bool.
Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false; otherwise *x != *y.
Remarks: Specializations of this function template for which *x != *y is a core constant expression are constexpr functions.
template<class T, class U> constexpr bool operator<(const optional<T>& x, const optional<U>& y);
Mandates: *x < *y is well-formed and its result is convertible to bool.
Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y.
Remarks: Specializations of this function template for which *x < *y is a core constant expression are constexpr functions.
template<class T, class U> constexpr bool operator>(const optional<T>& x, const optional<U>& y);
Mandates: The expression *x > *y is well-formed and its result is convertible to bool.
Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y.
Remarks: Specializations of this function template for which *x > *y is a core constant expression are constexpr functions.
template<class T, class U> constexpr bool operator<=(const optional<T>& x, const optional<U>& y);
Mandates: The expression *x <= *y is well-formed and its result is convertible to bool.
Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y.
Remarks: Specializations of this function template for which *x <= *y is a core constant expression are constexpr functions.
template<class T, class U> constexpr bool operator>=(const optional<T>& x, const optional<U>& y);
Mandates: The expression *x >= *y is well-formed and its result is convertible to bool.
Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y.
Remarks: Specializations of this function template for which *x >= *y is a core constant expression are constexpr functions.
template<class T, three_­way_­comparable_­with<T> U> constexpr compare_three_way_result_t<T,U> operator<=>(const optional<T>& x, const optional<U>& y);
Returns: If x && y, *x <=> *y; otherwise bool(x) <=> bool(y).
Remarks: Specializations of this function template for which *x <=> *y is a core constant expression are constexpr functions.

20.6.7 Comparison with nullopt [optional.nullops]

template<class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept;
Returns: !x.
template<class T> constexpr strong_ordering operator<=>(const optional<T>& x, nullopt_t) noexcept;
Returns: bool(x) <=> false.

20.6.8 Comparison with T [optional.comp.with.t]

template<class T, class U> constexpr bool operator==(const optional<T>& x, const U& v);
Mandates: The expression *x == v is well-formed and its result is convertible to bool.
[Note 1:
T need not be Cpp17EqualityComparable.
— end note]
Effects: Equivalent to: return bool(x) ? *x == v : false;
template<class T, class U> constexpr bool operator==(const T& v, const optional<U>& x);
Mandates: The expression v == *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return bool(x) ? v == *x : false;
template<class T, class U> constexpr bool operator!=(const optional<T>& x, const U& v);
Mandates: The expression *x != v is well-formed and its result is convertible to bool.
Effects: Equivalent to: return bool(x) ? *x != v : true;
template<class T, class U> constexpr bool operator!=(const T& v, const optional<U>& x);
Mandates: The expression v != *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return bool(x) ? v != *x : true;
template<class T, class U> constexpr bool operator<(const optional<T>& x, const U& v);
Mandates: The expression *x < v is well-formed and its result is convertible to bool.
Effects: Equivalent to: return bool(x) ? *x < v : true;
template<class T, class U> constexpr bool operator<(const T& v, const optional<U>& x);
Mandates: The expression v < *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return bool(x) ? v < *x : false;
template<class T, class U> constexpr bool operator>(const optional<T>& x, const U& v);
Mandates: The expression *x > v is well-formed and its result is convertible to bool.
Effects: Equivalent to: return bool(x) ? *x > v : false;
template<class T, class U> constexpr bool operator>(const T& v, const optional<U>& x);
Mandates: The expression v > *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return bool(x) ? v > *x : true;
template<class T, class U> constexpr bool operator<=(const optional<T>& x, const U& v);
Mandates: The expression *x <= v is well-formed and its result is convertible to bool.
Effects: Equivalent to: return bool(x) ? *x <= v : true;
template<class T, class U> constexpr bool operator<=(const T& v, const optional<U>& x);
Mandates: The expression v <= *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return bool(x) ? v <= *x : false;
template<class T, class U> constexpr bool operator>=(const optional<T>& x, const U& v);
Mandates: The expression *x >= v is well-formed and its result is convertible to bool.
Effects: Equivalent to: return bool(x) ? *x >= v : false;
template<class T, class U> constexpr bool operator>=(const T& v, const optional<U>& x);
Mandates: The expression v >= *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return bool(x) ? v >= *x : true;
template<class T, three_­way_­comparable_­with<T> U> constexpr compare_three_way_result_t<T,U> operator<=>(const optional<T>& x, const U& v);
Effects: Equivalent to: return bool(x) ? *x <=> v : strong_­ordering​::​less;

20.6.9 Specialized algorithms [optional.specalg]

template<class T> void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_­move_­constructible_­v<T> is true and is_­swappable_­v<T> is true.
Effects: Calls x.swap(y).
template<class T> constexpr optional<decay_t<T>> make_optional(T&& v);
Returns: optional<decay_­t<T>>(std​::​forward<T>(v)).
template<class T, class...Args> constexpr optional<T> make_optional(Args&&... args);
Effects: Equivalent to: return optional<T>(in_­place, std​::​forward<Args>(args)...);
template<class T, class U, class... Args> constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
Effects: Equivalent to: return optional<T>(in_­place, il, std​::​forward<Args>(args)...);

20.6.10 Hash support [optional.hash]

template<class T> struct hash<optional<T>>;
The specialization hash<optional<T>> is enabled ([unord.hash]) if and only if hash<remove_­const_­t<T>> is enabled.
When enabled, for an object o of type optional<T>, if bool(o) == true, then hash<optional<T>>()(o) evaluates to the same value as hash<remove_­const_­t<T>>()(*o); otherwise it evaluates to an unspecified value.
The member functions are not guaranteed to be noexcept.

20.7 Variants [variant]

20.7.1 In general [variant.general]

A variant object holds and manages the lifetime of a value.
If the variant holds a value, that value's type has to be one of the template argument types given to variant.
These template arguments are called alternatives.

20.7.2 Header <variant> synopsis [variant.syn]

#include <compare> // see [compare.syn] namespace std { // [variant.variant], class template variant template<class... Types> class variant; // [variant.helper], variant helper classes template<class T> struct variant_size; // not defined template<class T> struct variant_size<const T>; template<class T> inline constexpr size_t variant_size_v = variant_size<T>::value; template<class... Types> struct variant_size<variant<Types...>>; template<size_t I, class T> struct variant_alternative; // not defined template<size_t I, class T> struct variant_alternative<I, const T>; template<size_t I, class T> using variant_alternative_t = typename variant_alternative<I, T>::type; template<size_t I, class... Types> struct variant_alternative<I, variant<Types...>>; inline constexpr size_t variant_npos = -1; // [variant.get], value access template<class T, class... Types> constexpr bool holds_alternative(const variant<Types...>&) noexcept; template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>&); template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&&); template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>&); template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&&); template<class T, class... Types> constexpr T& get(variant<Types...>&); template<class T, class... Types> constexpr T&& get(variant<Types...>&&); template<class T, class... Types> constexpr const T& get(const variant<Types...>&); template<class T, class... Types> constexpr const T&& get(const variant<Types...>&&); template<size_t I, class... Types> constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> get_if(variant<Types...>*) noexcept; template<size_t I, class... Types> constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> get_if(const variant<Types...>*) noexcept; template<class T, class... Types> constexpr add_pointer_t<T> get_if(variant<Types...>*) noexcept; template<class T, class... Types> constexpr add_pointer_t<const T> get_if(const variant<Types...>*) noexcept; // [variant.relops], relational operators template<class... Types> constexpr bool operator==(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator<(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator>(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&); template<class... Types> requires (three_way_comparable<Types> && ...) constexpr common_comparison_category_t<compare_three_way_result_t<Types>...> operator<=>(const variant<Types...>&, const variant<Types...>&); // [variant.visit], visitation template<class Visitor, class... Variants> constexpr see below visit(Visitor&&, Variants&&...); template<class R, class Visitor, class... Variants> constexpr R visit(Visitor&&, Variants&&...); // [variant.monostate], class monostate struct monostate; // [variant.monostate.relops], monostate relational operators constexpr bool operator==(monostate, monostate) noexcept; constexpr strong_ordering operator<=>(monostate, monostate) noexcept; // [variant.specalg], specialized algorithms template<class... Types> void swap(variant<Types...>&, variant<Types...>&) noexcept(see below); // [variant.bad.access], class bad_­variant_­access class bad_variant_access; // [variant.hash], hash support template<class T> struct hash; template<class... Types> struct hash<variant<Types...>>; template<> struct hash<monostate>; }

20.7.3 Class template variant [variant.variant]

20.7.3.1 General [variant.variant.general]

namespace std { template<class... Types> class variant { public: // [variant.ctor], constructors constexpr variant() noexcept(see below); constexpr variant(const variant&); constexpr variant(variant&&) noexcept(see below); template<class T> constexpr variant(T&&) noexcept(see below); template<class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&...); template<class T, class U, class... Args> constexpr explicit variant(in_place_type_t<T>, initializer_list<U>, Args&&...); template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&...); template<size_t I, class U, class... Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U>, Args&&...); // [variant.dtor], destructor ~variant(); // [variant.assign], assignment constexpr variant& operator=(const variant&); constexpr variant& operator=(variant&&) noexcept(see below); template<class T> variant& operator=(T&&) noexcept(see below); // [variant.mod], modifiers template<class T, class... Args> T& emplace(Args&&...); template<class T, class U, class... Args> T& emplace(initializer_list<U>, Args&&...); template<size_t I, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(Args&&...); template<size_t I, class U, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U>, Args&&...); // [variant.status], value status constexpr bool valueless_by_exception() const noexcept; constexpr size_t index() const noexcept; // [variant.swap], swap void swap(variant&) noexcept(see below); }; }
Any instance of variant at any given time either holds a value of one of its alternative types or holds no value.
When an instance of variant holds a value of alternative type T, it means that a value of type T, referred to as the variant object's contained value, is allocated within the storage of the variant object.
Implementations are not permitted to use additional storage, such as dynamic memory, to allocate the contained value.
The contained value shall be allocated in a region of the variant storage suitably aligned for all types in Types.
All types in Types shall meet the Cpp17Destructible requirements (Table 32).
A program that instantiates the definition of variant with no template arguments is ill-formed.

20.7.3.2 Constructors [variant.ctor]

In the descriptions that follow, let i be in the range [0, sizeof...(Types)), and be the type in Types.
constexpr variant() noexcept(see below);
Constraints: is_­default_­constructible_­v<> is true.
Effects: Constructs a variant holding a value-initialized value of type .
Postconditions: valueless_­by_­exception() is false and index() is 0.
Throws: Any exception thrown by the value-initialization of .
Remarks: This function is constexpr if and only if the value-initialization of the alternative type would satisfy the requirements for a constexpr function.
The expression inside noexcept is equivalent to is_­nothrow_­default_­constructible_­v<>.
[Note 1:
See also class monostate.
— end note]
constexpr variant(const variant& w);
Effects: If w holds a value, initializes the variant to hold the same alternative as w and direct-initializes the contained value with get<j>(w), where j is w.index().
Otherwise, initializes the variant to not hold a value.
Throws: Any exception thrown by direct-initializing any for all i.
Remarks: This constructor is defined as deleted unless is_­copy_­constructible_­v<> is true for all i.
If is_­trivially_­copy_­constructible_­v<> is true for all i, this constructor is trivial.
constexpr variant(variant&& w) noexcept(see below);
Constraints: is_­move_­constructible_­v<> is true for all i.
Effects: If w holds a value, initializes the variant to hold the same alternative as w and direct-initializes the contained value with get<j>(std​::​move(w)), where j is w.index().
Otherwise, initializes the variant to not hold a value.
Throws: Any exception thrown by move-constructing any for all i.
Remarks: The expression inside noexcept is equivalent to the logical AND of is_­nothrow_­move_­constructible_­v<> for all i.
If is_­trivially_­move_­constructible_­v<> is true for all i, this constructor is trivial.
template<class T> constexpr variant(T&& t) noexcept(see below);
Let be a type that is determined as follows: build an imaginary function FUN() for each alternative type for which x[] = {std​::​forward<T>(t)}; is well-formed for some invented variable x.
The overload FUN() selected by overload resolution for the expression FUN(std​::​forward<T>(​t)) defines the alternative which is the type of the contained value after construction.
Constraints:
  • sizeof...(Types) is nonzero,
  • is_­same_­v<remove_­cvref_­t<T>, variant> is false,
  • remove_­cvref_­t<T> is neither a specialization of in_­place_­type_­t nor a specialization of in_­place_­index_­t,
  • is_­constructible_­v<, T> is true, and
  • the expression FUN(std​::​forward<T>(t)) (with FUN being the above-mentioned set of imaginary functions) is well-formed.
    [Note 2:
    variant<string, string> v("abc"); is ill-formed, as both alternative types have an equally viable constructor for the argument.
    — end note]
Effects: Initializes *this to hold the alternative type and direct-initializes the contained value as if direct-non-list-initializing it with std​::​forward<T>(t).
Postconditions: holds_­alternative<>(*this) is true.
Throws: Any exception thrown by the initialization of the selected alternative .
Remarks: The expression inside noexcept is equivalent to is_­nothrow_­constructible_­v<, T>.
If 's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&... args);
Constraints:
  • There is exactly one occurrence of T in Types... and
  • is_­constructible_­v<T, Args...> is true.
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std​::​forward<Args>(args)....
Postconditions: holds_­alternative<T>(*this) is true.
Throws: Any exception thrown by calling the selected constructor of T.
Remarks: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<class T, class U, class... Args> constexpr explicit variant(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Constraints:
  • There is exactly one occurrence of T in Types... and
  • is_­constructible_­v<T, initializer_­list<U>&, Args...> is true.
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std​::​forward<Args>(args)....
Postconditions: holds_­alternative<T>(*this) is true.
Throws: Any exception thrown by calling the selected constructor of T.
Remarks: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args);
Constraints:
  • I is less than sizeof...(Types) and
  • is_­constructible_­v<, Args...> is true.
Effects: Initializes the contained value as if direct-non-list-initializing an object of type with the arguments std​::​forward<Args>(args)....
Postconditions: index() is I.
Throws: Any exception thrown by calling the selected constructor of .
Remarks: If 's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<size_t I, class U, class... Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&... args);
Constraints:
  • I is less than sizeof...(Types) and
  • is_­constructible_­v<, initializer_­list<U>&, Args...> is true.
Effects: Initializes the contained value as if direct-non-list-initializing an object of type with the arguments il, std​::​forward<Args>(args)....
Postconditions: index() is I.
Remarks: If 's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.

20.7.3.3 Destructor [variant.dtor]

~variant();
Effects: If valueless_­by_­exception() is false, destroys the currently contained value.
Remarks: If is_­trivially_­destructible_­v<> is true for all , then this destructor is trivial.

20.7.3.4 Assignment [variant.assign]

constexpr variant& operator=(const variant& rhs);
Let j be rhs.index().
Effects:
  • If neither *this nor rhs holds a value, there is no effect.
  • Otherwise, if *this holds a value but rhs does not, destroys the value contained in *this and sets *this to not hold a value.
  • Otherwise, if index() == j, assigns the value contained in rhs to the value contained in *this.
  • Otherwise, if either is_­nothrow_­copy_­constructible_­v<> is true or is_­nothrow_­move_­constructible_­v<> is false, equivalent to emplace<j>(get<j>(rhs)).
  • Otherwise, equivalent to operator=(variant(rhs)).
Postconditions: index() == rhs.index().
Returns: *this.
Remarks: This operator is defined as deleted unless is_­copy_­constructible_­v<> && is_­copy_­assignable_­v<> is true for all i.
If is_­trivially_­copy_­constructible_­v<> && is_­trivially_­copy_­assignable_­v<> && is_­trivially_­destructible_­v<> is true for all i, this assignment operator is trivial.
constexpr variant& operator=(variant&& rhs) noexcept(see below);
Let j be rhs.index().
Constraints: is_­move_­constructible_­v<> && is_­move_­assignable_­v<> is true for all i.
Effects:
  • If neither *this nor rhs holds a value, there is no effect.
  • Otherwise, if *this holds a value but rhs does not, destroys the value contained in *this and sets *this to not hold a value.
  • Otherwise, if index() == j, assigns get<j>(std​::​move(rhs)) to the value contained in *this.
  • Otherwise, equivalent to emplace<j>(get<j>(std​::​move(rhs))).
Returns: *this.
Remarks: If is_­trivially_­move_­constructible_­v<> && is_­trivially_­move_­assignable_­v<> && is_­trivially_­destructible_­v<> is true for all i, this assignment operator is trivial.
The expression inside noexcept is equivalent to is_­nothrow_­move_­constructible_­v<> && is_­nothrow_­move_­assignable_­v<> for all i.
  • If an exception is thrown during the call to 's move construction (with j being rhs.index()), the variant will hold no value.
  • If an exception is thrown during the call to 's move assignment, the state of the contained value is as defined by the exception safety guarantee of 's move assignment; index() will be j.
template<class T> variant& operator=(T&& t) noexcept(see below);
Let be a type that is determined as follows: build an imaginary function FUN() for each alternative type for which x[] = {std​::​forward<T>(t)}; is well-formed for some invented variable x.
The overload FUN() selected by overload resolution for the expression FUN(std​::​forward<T>(​t)) defines the alternative which is the type of the contained value after assignment.
Constraints:
  • is_­same_­v<remove_­cvref_­t<T>, variant> is false,
  • is_­assignable_­v<&, T> && is_­constructible_­v<, T> is true, and
  • the expression FUN(std​::​forward<T>(t)) (with FUN being the above-mentioned set of imaginary functions) is well-formed.
    [Note 1:
    variant<string, string> v; v = "abc"; is ill-formed, as both alternative types have an equally viable constructor for the argument.
    — end note]
Effects:
  • If *this holds a , assigns std​::​forward<T>(t) to the value contained in *this.
  • Otherwise, if is_­nothrow_­constructible_­v<, T> || !is_­nothrow_­move_­constructible_­v<> is true, equivalent to emplace<j>(std​::​forward<T>(t)).
  • Otherwise, equivalent to operator=(variant(std​::​forward<T>(t))).
Postconditions: holds_­alternative<>(*this) is true, with selected by the imaginary function overload resolution described above.
Returns: *this.
Remarks: The expression inside noexcept is equivalent to: is_nothrow_assignable_v<T&, T> && is_nothrow_constructible_v<T, T>
  • If an exception is thrown during the assignment of std​::​forward<T>(t) to the value contained in *this, the state of the contained value and t are as defined by the exception safety guarantee of the assignment expression; valueless_­by_­exception() will be false.
  • If an exception is thrown during the initialization of the contained value, the variant object is permitted to not hold a value.

20.7.3.5 Modifiers [variant.mod]

template<class T, class... Args> T& emplace(Args&&... args);
Constraints: is_­constructible_­v<T, Args...> is true, and T occurs exactly once in Types.
Effects: Equivalent to: return emplace<I>(std::forward<Args>(args)...); where I is the zero-based index of T in Types.
template<class T, class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);
Constraints: is_­constructible_­v<T, initializer_­list<U>&, Args...> is true, and T occurs exactly once in Types.
Effects: Equivalent to: return emplace<I>(il, std::forward<Args>(args)...); where I is the zero-based index of T in Types.
template<size_t I, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);
Mandates: .
Constraints: is_­constructible_­v<, Args...> is true.
Effects: Destroys the currently contained value if valueless_­by_­exception() is false.
Then initializes the contained value as if direct-non-list-initializing a value of type with the arguments std​::​forward<Args>(args)....
Postconditions: index() is I.
Returns: A reference to the new contained value.
Throws: Any exception thrown during the initialization of the contained value.
Remarks: If an exception is thrown during the initialization of the contained value, the variant is permitted to not hold a value.
template<size_t I, class U, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U> il, Args&&... args);
Mandates: .
Constraints: is_­constructible_­v<, initializer_­list<U>&, Args...> is true.
Effects: Destroys the currently contained value if valueless_­by_­exception() is false.
Then initializes the contained value as if direct-non-list-initializing a value of type with the arguments il, std​::​forward<Args>(args)....
Postconditions: index() is I.
Returns: A reference to the new contained value.
Throws: Any exception thrown during the initialization of the contained value.
Remarks: If an exception is thrown during the initialization of the contained value, the variant is permitted to not hold a value.

20.7.3.6 Value status [variant.status]

constexpr bool valueless_by_exception() const noexcept;
Effects: Returns false if and only if the variant holds a value.
[Note 1:
A variant might not hold a value if an exception is thrown during a type-changing assignment or emplacement.
The latter means that even a variant<float, int> can become valueless_­by_­exception(), for instance by struct S { operator int() { throw 42; }}; variant<float, int> v{12.f}; v.emplace<1>(S());
— end note]
constexpr size_t index() const noexcept;
Effects: If valueless_­by_­exception() is true, returns variant_­npos.
Otherwise, returns the zero-based index of the alternative of the contained value.

20.7.3.7 Swap [variant.swap]

void swap(variant& rhs) noexcept(see below);
Mandates: is_­move_­constructible_­v<> is true for all i.
Preconditions: Lvalues of type are swappable ([swappable.requirements]).
Effects:
  • If valueless_­by_­exception() && rhs.valueless_­by_­exception() no effect.
  • Otherwise, if index() == rhs.index(), calls swap(get<i>(*this), get<i>(rhs)) where i is index().
  • Otherwise, exchanges values of rhs and *this.
Throws: If index() == rhs.index(), any exception thrown by swap(get<i>(*this), get<i>(rhs)) with i being index().
Otherwise, any exception thrown by the move constructor of or with i being index() and j being rhs.index().
Remarks: If an exception is thrown during the call to function swap(get<i>(*this), get<i>(rhs)), the states of the contained values of *this and of rhs are determined by the exception safety guarantee of swap for lvalues of with i being index().
If an exception is thrown during the exchange of the values of *this and rhs, the states of the values of *this and of rhs are determined by the exception safety guarantee of variant's move constructor.
The expression inside noexcept is equivalent to the logical AND of is_­nothrow_­move_­constructible_­v<> && is_­nothrow_­swappable_­v<> for all i.

20.7.4 variant helper classes [variant.helper]

template<class T> struct variant_size;
All specializations of variant_­size meet the Cpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_­constant<size_­t, N> for some N.
template<class T> struct variant_size<const T>;
Let VS denote variant_­size<T> of the cv-unqualified type T.
Then each specialization of the template meets the Cpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_­constant<size_­t, VS​::​value>.
template<class... Types> struct variant_size<variant<Types...>> : integral_constant<size_t, sizeof...(Types)> { };
template<size_t I, class T> struct variant_alternative<I, const T>;
Let VA denote variant_­alternative<I, T> of the cv-unqualified type T.
Then each specialization of the template meets the Cpp17TransformationTrait requirements ([meta.rqmts]) with a member typedef type that names the type add_­const_­t<VA​::​type>.
variant_alternative<I, variant<Types...>>::type
Mandates: .
Type: The type .

20.7.5 Value access [variant.get]

template<class T, class... Types> constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
Mandates: The type T occurs exactly once in Types.
Returns: true if index() is equal to the zero-based index of T in Types.
template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>& v); template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&& v); template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>& v); template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&& v);
Mandates: .
Effects: If v.index() is I, returns a reference to the object stored in the variant.
Otherwise, throws an exception of type bad_­variant_­access.
template<class T, class... Types> constexpr T& get(variant<Types...>& v); template<class T, class... Types> constexpr T&& get(variant<Types...>&& v); template<class T, class... Types> constexpr const T& get(const variant<Types...>& v); template<class T, class... Types> constexpr const T&& get(const variant<Types...>&& v);
Mandates: The type T occurs exactly once in Types.
Effects: If v holds a value of type T, returns a reference to that value.
Otherwise, throws an exception of type bad_­variant_­access.
template<size_t I, class... Types> constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> get_if(variant<Types...>* v) noexcept; template<size_t I, class... Types> constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> get_if(const variant<Types...>* v) noexcept;
Mandates: .
Returns: A pointer to the value stored in the variant, if v != nullptr and v->index() == I.
Otherwise, returns nullptr.
template<class T, class... Types> constexpr add_pointer_t<T> get_if(variant<Types...>* v) noexcept; template<class T, class... Types> constexpr add_pointer_t<const T> get_if(const variant<Types...>* v) noexcept;
Mandates: The type T occurs exactly once in Types.
Effects: Equivalent to: return get_­if<i>(v); with i being the zero-based index of T in Types.

20.7.6 Relational operators [variant.relops]

template<class... Types> constexpr bool operator==(const variant<Types...>& v, const variant<Types...>& w);
Mandates: get<i>(v) == get<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.index() != w.index(), false; otherwise if v.valueless_­by_­exception(), true; otherwise get<i>(v) == get<i>(w) with i being v.index().
template<class... Types> constexpr bool operator!=(const variant<Types...>& v, const variant<Types...>& w);
Mandates: get<i>(v) != get<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.index() != w.index(), true; otherwise if v.valueless_­by_­exception(), false; otherwise get<i>(v) != get<i>(w) with i being v.index().
template<class... Types> constexpr bool operator<(const variant<Types...>& v, const variant<Types...>& w);
Mandates: get<i>(v) < get<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If w.valueless_­by_­exception(), false; otherwise if v.valueless_­by_­exception(), true; otherwise, if v.index() < w.index(), true; otherwise if v.index() > w.index(), false; otherwise get<i>(v) < get<i>(w) with i being v.index().
template<class... Types> constexpr bool operator>(const variant<Types...>& v, const variant<Types...>& w);
Mandates: get<i>(v) > get<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.valueless_­by_­exception(), false; otherwise if w.valueless_­by_­exception(), true; otherwise, if v.index() > w.index(), true; otherwise if v.index() < w.index(), false; otherwise get<i>(v) > get<i>(w) with i being v.index().
template<class... Types> constexpr bool operator<=(const variant<Types...>& v, const variant<Types...>& w);
Mandates: get<i>(v) <= get<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.valueless_­by_­exception(), true; otherwise if w.valueless_­by_­exception(), false; otherwise, if v.index() < w.index(), true; otherwise if v.index() > w.index(), false; otherwise get<i>(v) <= get<i>(w) with i being v.index().
template<class... Types> constexpr bool operator>=(const variant<Types...>& v, const variant<Types...>& w);
Mandates: get<i>(v) >= get<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If w.valueless_­by_­exception(), true; otherwise if v.valueless_­by_­exception(), false; otherwise, if v.index() > w.index(), true; otherwise if v.index() < w.index(), false; otherwise get<i>(v) >= get<i>(w) with i being v.index().
template<class... Types> requires (three_way_comparable<Types> && ...) constexpr common_comparison_category_t<compare_three_way_result_t<Types>...> operator<=>(const variant<Types...>& v, const variant<Types...>& w);
Effects: Equivalent to: if (v.valueless_by_exception() && w.valueless_by_exception()) return strong_ordering::equal; if (v.valueless_by_exception()) return strong_ordering::less; if (w.valueless_by_exception()) return strong_ordering::greater; if (auto c = v.index() <=> w.index(); c != 0) return c; return get<i>(v) <=> get<i>(w); with i being v.index().

20.7.7 Visitation [variant.visit]

template<class Visitor, class... Variants> constexpr see below visit(Visitor&& vis, Variants&&... vars); template<class R, class Visitor, class... Variants> constexpr R visit(Visitor&& vis, Variants&&... vars);
Let n be sizeof...(Variants).
Let m be a pack of n values of type size_­t.
Such a pack is called valid if for all .
For each valid pack m, let e(m) denote the expression: INVOKE(std::forward<Visitor>(vis), get<m>(std::forward<Variants>(vars))...) // see [func.require] for the first form and INVOKE<R>(std::forward<Visitor>(vis), get<m>(std::forward<Variants>(vars))...) // see [func.require] for the second form.
Mandates: For each valid pack m, e(m) is a valid expression.
All such expressions are of the same type and value category.
Returns: e(m), where m is the pack for which is vars.index() for all .
The return type is decltype(e(m)) for the first form.
Throws: bad_­variant_­access if any variant in vars is valueless_­by_­exception().
Complexity: For , the invocation of the callable object is implemented in constant time, i.e., for , it does not depend on the number of alternative types of .
For , the invocation of the callable object has no complexity requirements.

20.7.8 Class monostate [variant.monostate]

struct monostate{};
The class monostate can serve as a first alternative type for a variant to make the variant type default constructible.

20.7.9 monostate relational operators [variant.monostate.relops]

constexpr bool operator==(monostate, monostate) noexcept { return true; } constexpr strong_ordering operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; }
[Note 1:
monostate objects have only a single state; they thus always compare equal.
— end note]

20.7.10 Specialized algorithms [variant.specalg]

template<class... Types> void swap(variant<Types...>& v, variant<Types...>& w) noexcept(see below);
Constraints: is_­move_­constructible_­v<> && is_­swappable_­v<> is true for all i.
Effects: Equivalent to v.swap(w).
Remarks: The expression inside noexcept is equivalent to noexcept(v.swap(w)).

20.7.11 Class bad_­variant_­access [variant.bad.access]

class bad_variant_access : public exception { public: // see [exception] for the specification of the special member functions const char* what() const noexcept override; };
Objects of type bad_­variant_­access are thrown to report invalid accesses to the value of a variant object.
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

20.7.12 Hash support [variant.hash]

template<class... Types> struct hash<variant<Types...>>;
The specialization hash<variant<Types...>> is enabled ([unord.hash]) if and only if every specialization in hash<remove_­const_­t<Types>>... is enabled.
The member functions are not guaranteed to be noexcept.
template<> struct hash<monostate>;
The specialization is enabled ([unord.hash]).

20.8 Storage for any type [any]

20.8.1 General [any.general]

Subclause [any] describes components that C++ programs may use to perform operations on objects of a discriminated type.
[Note 1:
The discriminated type can contain values of different types but does not attempt conversion between them, i.e., 5 is held strictly as an int and is not implicitly convertible either to "5" or to 5.0.
This indifference to interpretation but awareness of type effectively allows safe, generic containers of single values, with no scope for surprises from ambiguous conversions.
— end note]

20.8.2 Header <any> synopsis [any.synop]

namespace std { // [any.bad.any.cast], class bad_­any_­cast class bad_any_cast; // [any.class], class any class any; // [any.nonmembers], non-member functions void swap(any& x, any& y) noexcept; template<class T, class... Args> any make_any(Args&&... args); template<class T, class U, class... Args> any make_any(initializer_list<U> il, Args&&... args); template<class T> T any_cast(const any& operand); template<class T> T any_cast(any& operand); template<class T> T any_cast(any&& operand); template<class T> const T* any_cast(const any* operand) noexcept; template<class T> T* any_cast(any* operand) noexcept; }

20.8.3 Class bad_­any_­cast [any.bad.any.cast]

class bad_any_cast : public bad_cast { public: // see [exception] for the specification of the special member functions const char* what() const noexcept override; };
Objects of type bad_­any_­cast are thrown by a failed any_­cast.
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

20.8.4 Class any [any.class]

20.8.4.1 General [any.class.general]

namespace std { class any { public: // [any.cons], construction and destruction constexpr any() noexcept; any(const any& other); any(any&& other) noexcept; template<class T> any(T&& value); template<class T, class... Args> explicit any(in_place_type_t<T>, Args&&...); template<class T, class U, class... Args> explicit any(in_place_type_t<T>, initializer_list<U>, Args&&...); ~any(); // [any.assign], assignments any& operator=(