19 General utilities library [utilities]

19.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 38.
Table 38 β€” General utilities library summary
Subclause
Header(s)
Utility components
<utility>
Compile-time integer sequences
<utility>
Pairs
<utility>
Tuples
<tuple>
Optional objects
<optional>
Variants
<variant>
Storage for any type
<any>
Fixed-size sequences of bits
<bitset>
Memory
<memory>
<cstdlib>
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>

19.2 Utility components [utility]

19.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 <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

  // [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 bool operator!=(const pair<T1, T2>&, const pair<T1, T2>&);
  template<class T1, class T2>
    constexpr bool operator< (const pair<T1, T2>&, const pair<T1, T2>&);
  template<class T1, class T2>
    constexpr bool operator> (const pair<T1, T2>&, const pair<T1, T2>&);
  template<class T1, class T2>
    constexpr bool operator<=(const pair<T1, T2>&, const pair<T1, T2>&);
  template<class T1, class T2>
    constexpr bool operator>=(const pair<T1, T2>&, const pair<T1, T2>&);

  template<class T1, class T2>
    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> class tuple_size;
  template<size_t I, class T> class 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{};
}

19.2.2 swap [utility.swap]

template<class T> constexpr void swap(T& a, T& b) noexcept(see below);
Remarks: This function is a designated customization point ([namespace.std]) and shall not participate in overload resolution unless is_­move_­constructible_­v<T> is true and is_­move_­assignable_­v<T> is true.
The expression inside noexcept is equivalent to:
is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>
Requires: Type T shall be Cpp17MoveConstructible (Table 25) and Cpp17MoveAssignable (Table 27).
Effects: Exchanges values stored in two locations.
template<class T, size_t N> constexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v<T>);
Remarks: This function shall not participate in overload resolution unless is_­swappable_­v<T> is true.
Requires: a[i] shall be swappable with b[i] for all i in the range [0, N).
Effects: As if by swap_­ranges(a, a + N, b).

19.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;

19.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;
Returns: static_­cast<T&&>(t).
Remarks: If the second form is instantiated with an lvalue reference type, the program is ill-formed.
[ Example
:
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
:
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).

19.2.5 Function template as_­const [utility.as_const]

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

19.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
Remarks: If this function is odr-used, the program is ill-formed.
Remarks: The template parameter T of declval may be an incomplete type.
[ Example
:
template<class To, class From> decltype(static_cast<To>(declval<From>())) convert(From&&);
declares a function template convert which only participates in overloading if the type From can be explicitly converted to type To.
For another example see class template common_­type ([meta.trans.other]).
— end example
 ]

19.3 Compile-time integer sequences [intseq]

19.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
:
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
 ]

19.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); }
  };
}
T shall be an integer type.

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

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

19.4 Pairs [pairs]

19.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]).

19.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;
    explicit(see below) constexpr pair();
    explicit(see below) constexpr pair(const T1& x, const T2& y);
    template<class U1, class U2>
      explicit(see below) constexpr pair(U1&& x, U2&& y);
    template<class U1, class U2>
      explicit(see below) constexpr pair(const pair<U1, U2>& p);
    template<class U1, class U2>
      explicit(see below) constexpr pair(pair<U1, U2>&& p);
    template<class... Args1, class... Args2>
      pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args);

    pair& operator=(const pair& p);
    template<class U1, class U2>
      pair& operator=(const pair<U1, U2>& p);
    pair& operator=(pair&& p) noexcept(see below);
    template<class U1, class U2>
      pair& operator=(pair<U1, U2>&& p);

    void swap(pair& p) noexcept(see below);
  };

  template<class T1, class T2>
    pair(T1, T2) -> pair<T1, T2>;
}
Constructors and member functions of pair shall 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 shall be a constexpr function if and only if all required element-wise initializations for copy and move, 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.
explicit(see below) constexpr pair();
Effects: Value-initializes first and second.
Remarks: This constructor shall not participate in overload resolution unless is_­default_­constructible_­v<first_­type> is true and is_­default_­constructible_­v<second_­type> is true.
[ Note
:
This behavior can be implemented by a constructor template with default template arguments.
— end note
 ]
The expression inside explicit evaluates to true if and only if either first_­type or second_­type is not implicitly default-constructible.
[ Note
:
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
 ]
explicit(see below) constexpr pair(const T1& x, const T2& y);
Effects: Initializes first with x and second with y.
Remarks: This constructor shall not participate in overload resolution unless is_­copy_­constructible_­v<first_­type> is true and is_­copy_­constructible_­v<second_­type> is true.
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> explicit(see below) constexpr pair(U1&& x, U2&& y);
Effects: Initializes first with std::forward<U1>(x) and second with std::forward<U2>(y).
Remarks: This constructor shall not participate in overload resolution unless is_­constructible_­v<first_­type, U1&&> is true and is_­constructible_­v<second_­type, U2&&> is true.
The expression inside explicit is equivalent to:
!is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
template<class U1, class U2> explicit(see below) constexpr pair(const pair<U1, U2>& p);
Effects: Initializes members from the corresponding members of the argument.
Remarks: This constructor shall not participate in overload resolution unless is_­constructible_­v<first_­type, const U1&> is true and is_­constructible_­v<second_­type, const U2&> is true.
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> explicit(see below) constexpr pair(pair<U1, U2>&& p);
Effects: Initializes first with std::forward<U1>(p.first) and second with std::forward<U2>(​p.second).
Remarks: This constructor shall not participate in overload resolution unless is_­constructible_­v<first_­type, U1&&> is true and is_­constructible_­v<second_­type, U2&&> is true.
The expression inside explicit is equivalent to:
!is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
template<class... Args1, class... Args2> pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args);
Requires: 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.
pair& operator=(const pair& p);
Effects: Assigns p.first to first and p.second to second.
Remarks: This operator shall be defined as deleted unless is_­copy_­assignable_­v<first_­type> is true and is_­copy_­assignable_­v<second_­type> is true.
Returns: *this.
template<class U1, class U2> pair& operator=(const pair<U1, U2>& p);
Effects: Assigns p.first to first and p.second to second.
Remarks: This operator shall not participate in overload resolution unless is_­assignable_­v<first_­type&, const U1&> is true and is_­assignable_­v<second_­type&, const U2&> is true.
Returns: *this.
pair& operator=(pair&& p) noexcept(see below);
Effects: Assigns to first with std::forward<first_­type>(p.first) and to second with
std::forward<second_­type>(p.second).
Remarks: This operator shall not participate in overload resolution unless is_­move_­assignable_­v<first_­type> is true and is_­move_­assignable_­v<second_­type> is true.
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_assignable_v<T1> && is_nothrow_move_assignable_v<T2>
Returns: *this.
template<class U1, class U2> pair& operator=(pair<U1, U2>&& p);
Effects: Assigns to first with std::forward<U1>(p.first) and to second with
std::forward<U2>(p.second).
Remarks: This operator shall not participate in overload resolution unless is_­assignable_­v<first_­type&, U1&&> is true and is_­assignable_­v<second_­type&, U2&&> is true.
Returns: *this.
void swap(pair& p) noexcept(see below);
Requires: first shall be swappable with ([swappable.requirements]) p.first and second shall be 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>

19.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 bool operator!=(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: !(x == y).
template<class T1, class T2> constexpr bool operator<(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: x.first < y.first || (!(y.first < x.first) && x.second < y.second).
template<class T1, class T2> constexpr bool operator>(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: y < x.
template<class T1, class T2> constexpr bool operator<=(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: !(y < x).
template<class T1, class T2> constexpr bool operator>=(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: !(x < y).
template<class T1, class T2> void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
Effects: As if by x.swap(y).
Remarks: This function shall not participate in overload resolution unless is_­swappable_­v<T1> is true and is_­swappable_­v<T2> is true.
template<class T1, class T2> constexpr pair<V1, V2> make_pair(T1&& x, T2&& y);
Returns: pair<V1, V2>(std::forward<T1>(x), std::forward<T2>(y)), where V1 and V2 are determined as follows: Let Ui be decay_­t<Ti> for each Ti.
If Ui is a specialization of reference_­wrapper, then Vi is Ui::type&, otherwise Vi is Ui.
[ Example
:
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
 ]

19.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> { };
tuple_element<I, pair<T1, T2>>::type
Requires: I < 2.
The program is ill-formed if I is out of bounds.
Value: The type T1 if I == 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;
Returns: If I == 0 returns a reference to p.first; if I == 1 returns a reference to p.second; otherwise the program is ill-formed.
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;
Requires: T1 and T2 are distinct types.
Otherwise, the program is ill-formed.
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;
Requires: T1 and T2 are distinct types.
Otherwise, the program is ill-formed.
Returns: A reference to p.second.

19.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.

19.5 Tuples [tuple]

19.5.1 In general [tuple.general]

This subclause 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.

19.5.2 Header <tuple> synopsis [tuple.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<VTypes...> 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> class tuple_size;                  // not defined
  template<class T> class tuple_size<const T>;
  template<class T> class tuple_size<volatile T>;
  template<class T> class tuple_size<const volatile T>;

  template<class... Types> class tuple_size<tuple<Types...>>;

  template<size_t I, class T> class tuple_element;     // not defined
  template<size_t I, class T> class tuple_element<I, const T>;
  template<size_t I, class T> class tuple_element<I, volatile T>;
  template<size_t I, class T> class tuple_element<I, const volatile T>;

  template<size_t I, class... Types>
    class 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 bool operator!=(const tuple<TTypes...>&, const tuple<UTypes...>&);
  template<class... TTypes, class... UTypes>
    constexpr bool operator<(const tuple<TTypes...>&, const tuple<UTypes...>&);
  template<class... TTypes, class... UTypes>
    constexpr bool operator>(const tuple<TTypes...>&, const tuple<UTypes...>&);
  template<class... TTypes, class... UTypes>
    constexpr bool operator<=(const tuple<TTypes...>&, const tuple<UTypes...>&);
  template<class... TTypes, class... UTypes>
    constexpr bool 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>
    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;
}

19.5.3 Class template tuple [tuple.tuple]

namespace std {
  template<class... Types>
  class tuple {
  public:
    // [tuple.cnstr], tuple construction
    explicit(see below) constexpr tuple();
    explicit(see below) constexpr tuple(const Types&...);          // only if sizeof...(Types) >= 1
    template<class... UTypes>
      explicit(see below) constexpr tuple(UTypes&&...);            // only if sizeof...(Types) >= 1

    tuple(const tuple&) = default;
    tuple(tuple&&) = default;

    template<class... UTypes>
      explicit(see below) constexpr tuple(const tuple<UTypes...>&);
    template<class... UTypes>
      explicit(see below) constexpr tuple(tuple<UTypes...>&&);

    template<class U1, class U2>
      explicit(see below) constexpr tuple(const pair<U1, U2>&);    // only if sizeof...(Types) == 2
    template<class U1, class U2>
      explicit(see below) constexpr tuple(pair<U1, U2>&&);         // only if sizeof...(Types) == 2

    // allocator-extended constructors
    template<class Alloc>
      tuple(allocator_arg_t, const Alloc& a);
    template<class Alloc>
      explicit(see below) tuple(allocator_arg_t, const Alloc& a, const Types&...);
    template<class Alloc, class... UTypes>
      explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
    template<class Alloc>
      tuple(allocator_arg_t, const Alloc& a, const tuple&);
    template<class Alloc>
      tuple(allocator_arg_t, const Alloc& a, tuple&&);
    template<class Alloc, class... UTypes>
      explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
    template<class Alloc, class... UTypes>
      explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
    template<class Alloc, class U1, class U2>
      explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
    template<class Alloc, class U1, class U2>
      explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);

    // [tuple.assign], tuple assignment
    tuple& operator=(const tuple&);
    tuple& operator=(tuple&&) noexcept(see below);

    template<class... UTypes>
      tuple& operator=(const tuple<UTypes...>&);
    template<class... UTypes>
      tuple& operator=(tuple<UTypes...>&&);

    template<class U1, class U2>
      tuple& operator=(const pair<U1, U2>&);            // only if sizeof...(Types) == 2
    template<class U1, class U2>
      tuple& operator=(pair<U1, U2>&&);                 // only if sizeof...(Types) == 2

    // [tuple.swap], tuple swap
    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...>;
}

19.5.3.1 Construction [tuple.cnstr]

In the descriptions that follow, let i be in the range [0, sizeof...(Types)) in order, T be the type in Types, and U 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 shall be a constexpr function if and only if all required element-wise initializations for copy and move, respectively, would satisfy the requirements for a constexpr function.
The defaulted move and copy constructor of tuple<> shall be constexpr functions.
If is_­trivially_­destructible_­v<T> is true for all T, then the destructor of tuple is trivial.
explicit(see below) constexpr tuple();
Effects: Value-initializes each element.
Remarks: This constructor shall not participate in overload resolution unless is_­default_­constructible_­v<T> is true for all i.
[ Note
:
This behavior can be implemented by a constructor template with default template arguments.
— end note
 ]
The expression inside explicit evaluates to true if and only if T is not implicitly default-constructible for at least one i.
[ Note
:
This behavior can be implemented with a trait that checks whether a const T& can be initialized with {}.
— end note
 ]
explicit(see below) constexpr tuple(const Types&...);
Effects: Initializes each element with the value of the corresponding parameter.
Remarks: This constructor shall not participate in overload resolution unless sizeof...(Types) >= 1 and is_­copy_­constructible_­v<T> is true for all i.
The expression inside explicit is equivalent to:
!conjunction_v<is_convertible<const Types&, Types>...>
template<class... UTypes> explicit(see below) constexpr tuple(UTypes&&... u);
Effects: Initializes the elements in the tuple with the corresponding value in std::forward<UTypes>(u).
Remarks: This constructor shall not participate in overload resolution unless sizeof...(Types) == sizeof...(UTypes) and sizeof...(Types) >= 1 and is_­constructible_­v<T, U&&> is true for all i.
The expression inside explicit is equivalent to:
!conjunction_v<is_convertible<UTypes, Types>...>
tuple(const tuple& u) = default;
Requires: is_­copy_­constructible_­v<T> is true for all i.
Effects: Initializes each element of *this with the corresponding element of u.
tuple(tuple&& u) = default;
Requires: is_­move_­constructible_­v<T> is true for all i.
Effects: For all i, initializes the element of *this with std::forward<T>(get<i>(u)).
template<class... UTypes> explicit(see below) constexpr tuple(const tuple<UTypes...>& u);
Effects: Initializes each element of *this with the corresponding element of u.
Remarks: This constructor shall not participate in overload resolution unless
  • sizeof...(Types) == sizeof...(UTypes) and
  • is_­constructible_­v<T, const U&> is true for all i, and
  • either sizeof...(Types) != 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.
The expression inside explicit is equivalent to:
!conjunction_v<is_convertible<const UTypes&, Types>...>
template<class... UTypes> explicit(see below) constexpr tuple(tuple<UTypes...>&& u);
Effects: For all i, initializes the element of *this with std::forward<U>(get<i>(u)).
Remarks: This constructor shall not participate in overload resolution unless
  • sizeof...(Types) == sizeof...(UTypes), and
  • is_­constructible_­v<T, U&&> is true for all i, and
  • either sizeof...(Types) != 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.
The expression inside explicit is equivalent to:
!conjunction_v<is_convertible<UTypes, Types>...>
template<class U1, class U2> explicit(see below) constexpr tuple(const pair<U1, U2>& u);
Effects: Initializes the first element with u.first and the second element with u.second.
Remarks: This constructor shall not participate in overload resolution unless sizeof...(Types) == 2, is_­constructible_­v<T, const U1&> is true and is_­constructible_­v<T, const U2&> is true.
The expression inside explicit is equivalent to:
!is_convertible_v<const U1&, T> || !is_convertible_v<const U2&, T>
template<class U1, class U2> explicit(see below) constexpr tuple(pair<U1, U2>&& u);
Effects: Initializes the first element with std::forward<U1>(u.first) and the second element with std::forward<U2>(u.second).
Remarks: This constructor shall not participate in overload resolution unless sizeof...(Types) == 2, is_­constructible_­v<T, U1&&> is true and is_­constructible_­v<T, U2&&> is true.
The expression inside explicit is equivalent to:
!is_convertible_v<U1, T> || !is_convertible_v<U2, T>
template<class Alloc> tuple(allocator_arg_t, const Alloc& a); template<class Alloc> explicit(see below) tuple(allocator_arg_t, const Alloc& a, const Types&...); template<class Alloc, class... UTypes> explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTypes&&...); template<class Alloc> tuple(allocator_arg_t, const Alloc& a, const tuple&); template<class Alloc> tuple(allocator_arg_t, const Alloc& a, tuple&&); template<class Alloc, class... UTypes> explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&); template<class Alloc, class... UTypes> explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&); template<class Alloc, class U1, class U2> explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); template<class Alloc, class U1, class U2> explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
Requires: Alloc shall satisfy the Cpp17Allocator requirements (Table 33).
Effects: Equivalent to the preceding constructors except that each element is constructed with uses-allocator construction.

19.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, T be the type in Types, and U be the type in a template parameter pack named UTypes, where indexing is zero-based.
tuple& operator=(const tuple& u);
Effects: Assigns each element of u to the corresponding element of *this.
Remarks: This operator shall be defined as deleted unless is_­copy_­assignable_­v<T> is true for all i.
Returns: *this.
tuple& operator=(tuple&& u) noexcept(see below);
Effects: For all i, assigns std::forward<T>(get<i>(u)) to get<i>(*this).
Remarks: This operator shall not participate in overload resolution unless is_­move_­assignable_­v<T> is true for all i.
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.
Returns: *this.
template<class... UTypes> tuple& operator=(const tuple<UTypes...>& u);
Effects: Assigns each element of u to the corresponding element of *this.
Remarks: This operator shall not participate in overload resolution unless sizeof...(Types) == sizeof...(UTypes) and is_­assignable_­v<T&, const U&> is true for all i.
Returns: *this.
template<class... UTypes> tuple& operator=(tuple<UTypes...>&& u);
Effects: For all i, assigns std::forward<U>(get<i>(u)) to get<i>(*this).
Remarks: This operator shall not participate in overload resolution unless is_­assignable_­v<T&, U&&> == true for all i and sizeof...(Types) == sizeof...(UTypes).
Returns: *this.
template<class U1, class U2> tuple& operator=(const pair<U1, U2>& u);
Effects: Assigns u.first to the first element of *this and u.second to the second element of *this.
Remarks: This operator shall not participate in overload resolution unless sizeof...(Types) == 2 and is_­assignable_­v<T&, const U1&> is true for the first type T in Types and is_­assignable_­v<T&, const U2&> is true for the second type T in Types.
Returns: *this.
template<class U1, class U2> tuple& operator=(pair<U1, U2>&& u);
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.
Remarks: This operator shall not participate in overload resolution unless sizeof...(Types) == 2 and is_­assignable_­v<T&, U1&&> is true for the first type T in Types and is_­assignable_­v<T&, U2&&> is true for the second type T in Types.
Returns: *this.

19.5.3.3 swap [tuple.swap]

void swap(tuple& rhs) noexcept(see below);
Requires: Each element in *this shall be swappable with ([swappable.requirements]) the corresponding element in rhs.
Effects: Calls swap for each element in *this and its corresponding element in rhs.
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.
Throws: Nothing unless one of the element-wise swap calls throws an exception.

19.5.3.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<VTypes...> make_tuple(TTypes&&... t);
The pack VTypes is defined as follows.
Let U be decay_­t<T> for each T in TTypes.
If U is a specialization of reference_­wrapper, then V in VTypes is U::type&, otherwise V is U.
Returns: tuple<VTypes...>(std::forward<TTypes>(t)...).
[ Example
:
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 variables, 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
:
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 T be the type in Tuples, U be remove_­reference_­t<T>, and tp be the parameter in the function parameter pack tpls, where all indexing is zero-based.
Requires: For all i, U shall be the type tuple<Args...>, where is the (possibly empty) cv-qualifier-seq and Args is the template parameter pack representing the element types in U.
Let A be the type in Args.
For all A the following requirements shall be satisfied:
  • If T is deduced as an lvalue reference type, then is_­constructible_­v<A, &> == true, otherwise
  • is_­constructible_­v<A, &&> == true.
Remarks: The types in CTypes shall be equal to the ordered sequence of the extended types Args..., Args..., , Args..., where n is equal to sizeof...(Tuples).
Let e... be the ordered sequence of tuple elements of the resulting tuple object corresponding to the type sequence Args.
Returns: A tuple object constructed by initializing the type element e in e... with
get<>(std::forward<T>(tp))
for each valid and each group e in order.
[ Note
:
An implementation may support additional types in the template parameter pack Tuples that support the tuple-like protocol, such as pair and array.
— end note
 ]

19.5.3.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
:
The type of T must be supplied as an explicit template parameter, as it cannot be deduced from the argument list.
— end note
 ]

19.5.3.6 Tuple helper classes [tuple.helper]

template<class T> struct tuple_size;
Remarks: All specializations of tuple_­size shall satisfy the Cpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_­constant<size_­t, N> for some N.
template<class... Types> class tuple_size<tuple<Types...>> : public integral_constant<size_t, sizeof...(Types)> { };
template<size_t I, class... Types> class tuple_element<I, tuple<Types...>> { public: using type = TI; };
Requires: I < sizeof...(Types).
The program is ill-formed if I is out of bounds.
Type: TI is the type of the I element of Types, where indexing is zero-based.
template<class T> class tuple_size<const T>; template<class T> class tuple_size<volatile T>; template<class T> class tuple_size<const volatile 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 of the three templates shall satisfy the Cpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of
integral_constant<size_t, TS::value>
Otherwise, they shall have 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
:
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 three templates are available when either of the headers <array> or <utility> are included.
template<size_t I, class T> class tuple_element<I, const T>; template<size_t I, class T> class tuple_element<I, volatile T>; template<size_t I, class T> class tuple_element<I, const volatile T>;
Let TE denote tuple_­element_­t<I, T> of the cv-unqualified type T.
Then each of the three templates shall satisfy the Cpp17TransformationTrait requirements ([meta.rqmts]) with a member typedef type that names the following type:
  • for the first specialization, add_­const_­t<TE>,
  • for the second specialization, add_­volatile_­t<TE>, and
  • for the third specialization, add_­cv_­t<TE>.
In addition to being available via inclusion of the <tuple> header, the three templates are available when either of the headers <array> or <utility> are included.

19.5.3.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;
Requires: I < sizeof...(Types).
The program is ill-formed if I is out of bounds.
Returns: A reference to the I element of t, where indexing is zero-based.
[ Note
:
[Note A] If a 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
:
[Note B] Constness is shallow.
If a 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;
Requires: The type T occurs exactly once in Types....
Otherwise, the program is ill-formed.
Returns: A reference to the element of t corresponding to the type T in Types....
[ Example
:
  const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6);
  const int& i1 = get<int>(t);        // OK. Not ambiguous. i1 == 1
  const int& i2 = get<const int>(t);  // OK. Not ambiguous. i2 == 2
  const double& d = get<double>(t);   // ERROR. ill-formed
— end example
 ]
[ Note
:
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
 ]

19.5.3.8 Relational operators [tuple.rel]

template<class... TTypes, class... UTypes> constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Requires: For all i, where 0 <= i and i < sizeof...(TTypes), get<i>(t) == get<i>(u) is a valid expression returning a type that is convertible to bool.
sizeof...(TTypes) == 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.
Effects: 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 bool operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Returns: !(t == u).
template<class... TTypes, class... UTypes> constexpr bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Requires: For all i, where 0 <= i and i < sizeof...(TTypes), both get<i>(t) < get<i>(u) and get<i>(u) < get<i>(t) are valid expressions returning types that are convertible to bool.
sizeof...(TTypes) == sizeof...(UTypes).
Returns: The result of a lexicographical comparison between t and u.
The result is defined as: (bool)(get<0>(t) < get<0>(u)) || (!(bool)(get<0>(u) < get<0>(t)) && t < u), where r for some tuple r is a tuple containing all but the first element of r.
For any two zero-length tuples e and f, e < f returns false.
template<class... TTypes, class... UTypes> constexpr bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Returns: u < t.
template<class... TTypes, class... UTypes> constexpr bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Returns: !(u < t).
template<class... TTypes, class... UTypes> constexpr bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Returns: !(t < u).
[ Note
:
The above definitions for comparison functions do not require t (or u) to be constructed.
It may not even be possible, as t and u are not required to be copy constructible.
Also, all comparison functions are short circuited; they do not perform element accesses beyond what is required to determine the result of the comparison.
— end note
 ]

19.5.3.9 Tuple traits [tuple.traits]

template<class... Types, class Alloc> struct uses_allocator<tuple<Types...>, Alloc> : true_type { };
Requires: Alloc shall satisfy the Cpp17Allocator requirements (Table 33).
[ Note
:
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
 ]

19.5.3.10 Tuple specialized algorithms [tuple.special]

template<class... Types> void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
Remarks: This function shall not participate in overload resolution unless is_­swappable_­v<T> is true for all i, where .
The expression inside noexcept is equivalent to:
noexcept(x.swap(y))
Effects: As if by x.swap(y).

19.6 Optional objects [optional]

19.6.1 In general [optional.general]

This subclause 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.

19.6.2 Header <optional> synopsis [optional.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>&);

  // [optional.nullops], comparison with nullopt
  template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
  template<class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
  template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
  template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
  template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
  template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
  template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
  template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
  template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
  template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
  template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
  template<class T> constexpr bool operator>=(nullopt_t, const optional<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>&);

  // [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>>;
}

19.6.3 Class template optional [optional.optional]

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>
      explicit(see below) constexpr 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;
    optional& operator=(const optional&);
    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 an object type other than cv in_­place_­t or cv nullopt_­t and shall satisfy the Cpp17Destructible requirements (Table 29).

19.6.3.1 Constructors [optional.ctor]

constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept;
Ensures: *this does not contain a value.
Remarks: No contained value is initialized.
For every object type T these constructors shall be constexpr constructors.
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.
Ensures: bool(rhs) == bool(*this).
Throws: Any exception thrown by the selected constructor of T.
Remarks: This constructor shall be defined as deleted unless is_­copy_­constructible_­v<T> is true.
If is_­trivially_­copy_­constructible_­v<T> is true, this constructor shall be a constexpr constructor.
constexpr optional(optional&& rhs) noexcept(see below);
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.
Ensures: 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>.
This constructor shall not participate in overload resolution unless is_­move_­constructible_­v<T> is true.
If is_­trivially_­move_­constructible_­v<T> is true, this constructor shall be a constexpr constructor.
template<class... Args> constexpr explicit optional(in_place_t, Args&&... args);
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....
Ensures: *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 shall be a constexpr constructor.
This constructor shall not participate in overload resolution unless is_­constructible_­v<T, Args...> is true.
template<class U, class... Args> constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std::forward<Args>(args)....
Ensures: *this contains a value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: This constructor shall not participate in overload resolution unless is_­constructible_­v<T, initializer_­list<U>&, Args&&...> is true.
If T's constructor selected for the initialization is a constexpr constructor, this constructor shall be a constexpr constructor.
template<class U = T> explicit(see below) constexpr optional(U&& v);
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the expression std::forward<U>(v).
Ensures: *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 shall be a constexpr constructor.
This constructor shall not participate in overload resolution unless 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.
The expression inside explicit is equivalent to:
!is_convertible_v<U, T>
template<class U> explicit(see below) optional(const optional<U>& 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.
Ensures: bool(rhs) == bool(*this).
Throws: Any exception thrown by the selected constructor of T.
Remarks: This constructor shall not participate in overload resolution unless
  • 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.
The expression inside explicit is equivalent to:
!is_convertible_v<const U&, T>
template<class U> explicit(see below) optional(optional<U>&& 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 std::move(*rhs).
bool(rhs) is unchanged.
Ensures: bool(rhs) == bool(*this).
Throws: Any exception thrown by the selected constructor of T.
Remarks: This constructor shall not participate in overload resolution unless
  • 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.
The expression inside explicit is equivalent to:
!is_convertible_v<U, T>

19.6.3.2 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.

19.6.3.3 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.
Returns: *this.
Ensures: *this does not contain a value.
optional<T>& operator=(const optional& rhs);
Effects: See Table 39.
Table 39 β€” optional::operator=(const optional&) effects
*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
Returns: *this.
Ensures: bool(rhs) == bool(*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 shall be defined as deleted unless is_­copy_­constructible_­v<T> is true and is_­copy_­assignable_­v<T> is true.
optional<T>& operator=(optional&& rhs) noexcept(see below);
Effects: See Table 40.
The result of the expression bool(rhs) remains unchanged.
Table 40 β€” optional::operator=(optional&&) effects
*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
Returns: *this.
Ensures: bool(rhs) == bool(*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.
This operator shall not participate in overload resolution unless is_­move_­constructible_­v<T> is true and is_­move_­assignable_­v<T> is true.
template<class U = T> optional<T>& operator=(U&& v);
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).
Returns: *this.
Ensures: *this contains a value.
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.
This function shall not participate in overload resolution unless 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.
template<class U> optional<T>& operator=(const optional<U>& rhs);
Effects: See Table 41.
Table 41 β€” optional::operator=(const optional<U>&) effects
*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
Returns: *this.
Ensures: bool(rhs) == bool(*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.
This function shall not participate in overload resolution unless
  • 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.
template<class U> optional<T>& operator=(optional<U>&& rhs);
Effects: See Table 42.
The result of the expression bool(rhs) remains unchanged.
Table 42 β€” optional::operator=(optional<U>&&) effects
*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
Returns: *this.
Ensures: bool(rhs) == bool(*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.
This function shall not participate in overload resolution unless
  • 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.
template<class... Args> T& emplace(Args&&... args);
Requires: 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)....
Ensures: *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);
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)....
Ensures: *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.
This function shall not participate in overload resolution unless is_­constructible_­v<T, initializer_­list<U>&, Args&&...> is true.

19.6.3.4 Swap [optional.swap]

void swap(optional& rhs) noexcept(see below);
Requires: Lvalues of type T shall be swappable and is_­move_­constructible_­v<T> is true.
Effects: See Table 43.
Table 43 β€” optional::swap(optional&) effects
*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 43.
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.

19.6.3.5 Observers [optional.observe]

constexpr const T* operator->() const; constexpr T* operator->();
Requires: *this contains a value.
Returns: val.
Throws: Nothing.
Remarks: These functions shall be constexpr functions.
constexpr const T& operator*() const&; constexpr T& operator*() &;
Requires: *this contains a value.
Returns: *val.
Throws: Nothing.
Remarks: These functions shall be constexpr functions.
constexpr T&& operator*() &&; constexpr const T&& operator*() const&&;
Requires: *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 shall be a constexpr function.
constexpr bool has_value() const noexcept;
Returns: true if and only if *this contains a value.
Remarks: This function shall be 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&;
Effects: Equivalent to:
return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
Remarks: If is_­copy_­constructible_­v<T> && is_­convertible_­v<U&&, T> is false, the program is ill-formed.
template<class U> constexpr T value_or(U&& v) &&;
Effects: Equivalent to:
return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));
Remarks: If is_­move_­constructible_­v<T> && is_­convertible_­v<U&&, T> is false, the program is ill-formed.

19.6.3.6 Modifiers [optional.mod]

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

19.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.

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

class bad_optional_access : public exception {
public:
  bad_optional_access();
};
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.
bad_optional_access();
Effects: Constructs an object of class bad_­optional_­access.
Ensures: what() returns an implementation-defined ntbs.

19.6.6 Relational operators [optional.relops]

template<class T, class U> constexpr bool operator==(const optional<T>& x, const optional<U>& y);
Requires: The expression *x == *y shall be well-formed and its result shall be convertible to bool.
[ Note
:
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 shall be constexpr functions.
template<class T, class U> constexpr bool operator!=(const optional<T>& x, const optional<U>& y);
Requires: The expression *x != *y shall be well-formed and its result shall be 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 shall be constexpr functions.
template<class T, class U> constexpr bool operator<(const optional<T>& x, const optional<U>& y);
Requires: *x < *y shall be well-formed and its result shall be 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 shall be constexpr functions.
template<class T, class U> constexpr bool operator>(const optional<T>& x, const optional<U>& y);
Requires: The expression *x > *y shall be well-formed and its result shall be 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 shall be constexpr functions.
template<class T, class U> constexpr bool operator<=(const optional<T>& x, const optional<U>& y);
Requires: The expression *x <= *y shall be well-formed and its result shall be 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 shall be constexpr functions.
template<class T, class U> constexpr bool operator>=(const optional<T>& x, const optional<U>& y);
Requires: The expression *x >= *y shall be well-formed and its result shall be 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 shall be constexpr functions.

19.6.7 Comparison with nullopt [optional.nullops]

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

19.6.8 Comparison with T [optional.comp_with_t]

template<class T, class U> constexpr bool operator==(const optional<T>& x, const U& v);
Requires: The expression *x == v shall be well-formed and its result shall be convertible to bool.
[ Note
:
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);
Requires: The expression v == *x shall be well-formed and its result shall be 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);
Requires: The expression *x != v shall be well-formed and its result shall be 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);
Requires: The expression v != *x shall be well-formed and its result shall be 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);
Requires: The expression *x < v shall be well-formed and its result shall be 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);
Requires: The expression v < *x shall be well-formed and its result shall be 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);
Requires: The expression *x > v shall be well-formed and its result shall be 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);
Requires: The expression v > *x shall be well-formed and its result shall be 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);
Requires: The expression *x <= v shall be well-formed and its result shall be 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);
Requires: The expression v <= *x shall be well-formed and its result shall be 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);
Requires: The expression *x >= v shall be well-formed and its result shall be 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);
Requires: The expression v >= *x shall be well-formed and its result shall be convertible to bool.
Effects: Equivalent to: return bool(x) ? v >= *x : true;

19.6.9 Specialized algorithms [optional.specalg]

template<class T> void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)));
Effects: Calls x.swap(y).
Remarks: This function shall not participate in overload resolution unless is_­move_­constructible_­v<T> is true and is_­swappable_­v<T> is true.
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)...);

19.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) shall evaluate 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.

19.7 Variants [variant]

19.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.

19.7.2 Header <variant> synopsis [variant.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> struct variant_size<volatile T>;
  template<class T> struct variant_size<const volatile 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> struct variant_alternative<I, volatile T>;
  template<size_t I, class T> struct variant_alternative<I, const volatile 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...>&);

  // [variant.visit], visitation
  template<class Visitor, class... Variants>
    constexpr see below visit(Visitor&&, Variants&&...);

  // [variant.monostate], class monostate
  struct monostate;

  // [variant.monostate.relops], monostate relational operators
  constexpr bool operator==(monostate, monostate) noexcept;
  constexpr bool operator!=(monostate, monostate) noexcept;
  constexpr bool operator<(monostate, monostate) noexcept;
  constexpr bool operator>(monostate, monostate) noexcept;
  constexpr bool operator<=(monostate, monostate) noexcept;
  constexpr bool 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>;
}

19.7.3 Class template variant [variant.variant]

namespace std {
  template<class... Types>
  class variant {
  public:
    // [variant.ctor], constructors
    constexpr variant() noexcept(see below);
    variant(const variant&);
    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
    variant& operator=(const variant&);
    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 it 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....
It is implementation-defined whether over-aligned types are supported.
All types in Types... shall be (possibly cv-qualified) object types that are not arrays.
A program that instantiates the definition of variant with no template arguments is ill-formed.

19.7.3.1 Constructors [variant.ctor]

In the descriptions that follow, let i be in the range [0, sizeof...(Types)), and T be the type in Types....
constexpr variant() noexcept(see below);
Effects: Constructs a variant holding a value-initialized value of type T.
Ensures: valueless_­by_­exception() is false and index() is 0.
Throws: Any exception thrown by the value-initialization of T.
Remarks: This function shall be constexpr if and only if the value-initialization of the alternative type T would satisfy the requirements for a constexpr function.
The expression inside noexcept is equivalent to is_­nothrow_­default_­constructible_­v<T>.
This function shall not participate in overload resolution unless is_­default_­constructible_­v<T> is true.
[ Note
:
See also class monostate.
— end note
 ]
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 T for all i.
Remarks: This constructor shall be defined as deleted unless is_­copy_­constructible_­v<T> is true for all i.
variant(variant&& w) noexcept(see below);
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 T for all i.
Remarks: The expression inside noexcept is equivalent to the logical AND of is_­nothrow_­move_­constructible_­v<T> for all i.
This function shall not participate in overload resolution unless is_­move_­constructible_­v<T> is true for all i.
template<class T> constexpr variant(T&& t) noexcept(see below);
Let T be a type that is determined as follows: build an imaginary function FUN(T) for each alternative type T.
The overload FUN(T) selected by overload resolution for the expression FUN(std::forward<T>(​t)) defines the alternative T which is the type of the contained value after construction.
Effects: Initializes *this to hold the alternative type T and direct-initializes the contained value as if direct-non-list-initializing it with std::forward<T>(t).
Ensures: holds_­alternative<T>(*this) is true.
Throws: Any exception thrown by the initialization of the selected alternative T.
Remarks: This function shall not participate in overload resolution unless
  • 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, 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
:
variant<string, string> v("abc");
is ill-formed, as both alternative types have an equally viable constructor for the argument.
— end note
 ]
The expression inside noexcept is equivalent to is_­nothrow_­constructible_­v<T, T>.
If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.
template<class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&... args);
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....
Ensures: holds_­alternative<T>(*this) is true.
Throws: Any exception thrown by calling the selected constructor of T.
Remarks: This function shall not participate in overload resolution unless there is exactly one occurrence of T in Types... and is_­constructible_­v<T, Args...> is true.
If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.
template<class T, class U, class... Args> constexpr explicit variant(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std::forward<Args>(args)....
Ensures: holds_­alternative<T>(*this) is true.
Throws: Any exception thrown by calling the selected constructor of T.
Remarks: This function shall not participate in overload resolution unless there is exactly one occurrence of T in Types... and is_­constructible_­v<T, initializer_­list<U>&, Args...> is true.
If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.
template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args);
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....
Ensures: index() is I.
Throws: Any exception thrown by calling the selected constructor of T.
Remarks: This function shall not participate in overload resolution unless
  • I is less than sizeof...(Types) and
  • is_­constructible_­v<T, Args...> is true.
If T's selected constructor is a constexpr constructor, this constructor shall be 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);
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std::forward<Args>(args)....
Ensures: index() is I.
Remarks: This function shall not participate in overload resolution unless
  • I is less than sizeof...(Types) and
  • is_­constructible_­v<T, initializer_­list<U>&, Args...> is true.
If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.

19.7.3.2 Destructor [variant.dtor]

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

19.7.3.3 Assignment [variant.assign]

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<T> is true or is_­nothrow_­move_­constructible_­v<T> is false, equivalent to emplace<j>(get<j>(rhs)).
  • Otherwise, equivalent to operator=(variant(rhs)).
Returns: *this.
Ensures: index() == rhs.index().
Remarks: This operator shall be defined as deleted unless is_­copy_­constructible_­v<T> && is_­copy_­assignable_­v<T> is true for all i.
variant& operator=(variant&& rhs) noexcept(see below);
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 get<j>(std::move(rhs)) to the value contained in *this.
  • Otherwise, equivalent to emplace<j>(get<j>(std::move(rhs))).
Returns: *this.
Remarks: This function shall not participate in overload resolution unless is_­move_­constructible_­v<T> && is_­move_­assignable_­v<T> is true for all i.
The expression inside noexcept is equivalent to: is_­nothrow_­move_­constructible_­v<T> && is_­nothrow_­move_­assignable_­v<T> for all i.
  • If an exception is thrown during the call to T's move construction (with j being rhs.index()), the variant will hold no value.
  • If an exception is thrown during the call to T's move assignment, the state of the contained value is as defined by the exception safety guarantee of T's move assignment; index() will be j.
template<class T> variant& operator=(T&& t) noexcept(see below);
Let T be a type that is determined as follows: build an imaginary function FUN(T) for each alternative type T.
The overload FUN(T) selected by overload resolution for the expression FUN(std::forward<T>(​t)) defines the alternative T which is the type of the contained value after assignment.
Effects:
  • If *this holds a T, assigns std::forward<T>(t) to the value contained in *this.
  • Otherwise, if is_­nothrow_­constructible_­v<T, T> || !is_­nothrow_­move_­constructible_­v<T> is true, equivalent to emplace<j>(std::forward<T>(t)).
  • Otherwise, equivalent to operator=(variant(std::forward<T>(t))).
Ensures: holds_­alternative<T>(*this) is true, with T selected by the imaginary function overload resolution described above.
Returns: *this.
Remarks: This function shall not participate in overload resolution unless
  • is_­same_­v<remove_­cvref_­t<T>, variant> is false,
  • is_­assignable_­v<T&, T> && is_­constructible_­v<T, 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
:
variant<string, string> v;
v = "abc";
is ill-formed, as both alternative types have an equally viable constructor for the argument.
— end note
 ]
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 might not hold a value.

19.7.3.4 Modifiers [variant.mod]

template<class T, class... Args> T& emplace(Args&&... args);
Let I be the zero-based index of T in Types....
Effects: Equivalent to: return emplace<I>(std::forward<Args>(args)...);
Remarks: This function shall not participate in overload resolution unless is_­constructible_­v<T, Args...> is true, and T occurs exactly once in Types....
template<class T, class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);
Let I be the zero-based index of T in Types....
Effects: Equivalent to: return emplace<I>(il, std::forward<Args>(args)...);
Remarks: This function shall not participate in overload resolution unless is_­constructible_­v<T, initializer_­list<U>&, Args...> is true, and T occurs exactly once in Types....
template<size_t I, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);
Requires: I < sizeof...(Types).
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 T with the arguments std::forward<Args>(args)....
Ensures: index() is I.
Returns: A reference to the new contained value.
Throws: Any exception thrown during the initialization of the contained value.
Remarks: This function shall not participate in overload resolution unless is_­constructible_­v<T, Args...> is true.
If an exception is thrown during the initialization of the contained value, the variant might 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);
Requires: I < sizeof...(Types).
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 T with the arguments il, std::forward<Args>(args)....
Ensures: index() is I.
Returns: A reference to the new contained value.
Throws: Any exception thrown during the initialization of the contained value.
Remarks: This function shall not participate in overload resolution unless is_­constructible_­v<T, initializer_­list<U>&, Args...> is true.
If an exception is thrown during the initialization of the contained value, the variant might not hold a value.

19.7.3.5 Value status [variant.status]

constexpr bool valueless_by_exception() const noexcept;
Effects: Returns false if and only if the variant holds a value.
[ Note
:
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.

19.7.3.6 Swap [variant.swap]

void swap(variant& rhs) noexcept(see below);
Requires: Lvalues of type T shall be swappable ([swappable.requirements]) and is_­move_­constructible_­v<T> shall be true for all i.
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 T or T 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 T 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<T> && is_­nothrow_­swappable_­v<T> for all i.

19.7.4 variant helper classes [variant.helper]

template<class T> struct variant_size;
Remarks: All specializations of variant_­size shall satisfy the Cpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_­constant<size_­t, N> for some N.
template<class T> class variant_size<const T>; template<class T> class variant_size<volatile T>; template<class T> class variant_size<const volatile T>;
Let VS denote variant_­size<T> of the cv-unqualified type T.
Then each of the three templates shall satisfy 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> class variant_alternative<I, const T>; template<size_t I, class T> class variant_alternative<I, volatile T>; template<size_t I, class T> class variant_alternative<I, const volatile T>;
Let VA denote variant_­alternative<I, T> of the cv-unqualified type T.
Then each of the three templates shall meet the Cpp17TransformationTrait requirements ([meta.rqmts]) with a member typedef type that names the following type:
  • for the first specialization, add_­const_­t<VA::type>,
  • for the second specialization, add_­volatile_­t<VA::type>, and
  • for the third specialization, add_­cv_­t<VA::type>.
variant_alternative<I, variant<Types...>>::type
Requires: I < sizeof...(Types).
The program is ill-formed if I is out of bounds.
Value: The type T.

19.7.5 Value access [variant.get]

template<class T, class... Types> constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
Requires: The type T occurs exactly once in Types....
Otherwise, the program is ill-formed.
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);
Requires: I < sizeof...(Types).
Otherwise, the program is ill-formed.
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);
Requires: The type T occurs exactly once in Types....
Otherwise, the program is ill-formed.
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;
Requires: I < sizeof...(Types).
Otherwise, the program is ill-formed.
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;
Requires: The type T occurs exactly once in Types....
Otherwise, the program is ill-formed.
Effects: Equivalent to: return get_­if<i>(v); with i being the zero-based index of T in Types....

19.7.6 Relational operators [variant.relops]

template<class... Types> constexpr bool operator==(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) == get<i>(w) is a valid expression returning a type 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);
Requires: get<i>(v) != get<i>(w) is a valid expression returning a type 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);
Requires: get<i>(v) < get<i>(w) is a valid expression returning a type 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);
Requires: get<i>(v) > get<i>(w) is a valid expression returning a type 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);
Requires: get<i>(v) <= get<i>(w) is a valid expression returning a type 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);
Requires: get<i>(v) >= get<i>(w) is a valid expression returning a type 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().

19.7.7 Visitation [variant.visit]

template<class Visitor, class... Variants> constexpr see below 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]
Requires: For each valid pack m, e(m) shall be a valid expression.
All such expressions shall be of the same type and value category; otherwise, the program is ill-formed.
Returns: e(m), where m is the pack for which m is vars.index() for all .
The return type is decltype(e(m)).
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 Variants.
For , the invocation of the callable object has no complexity requirements.

19.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.

19.7.9 monostate relational operators [variant.monostate.relops]

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

19.7.10 Specialized algorithms [variant.specalg]

template<class... Types> void swap(variant<Types...>& v, variant<Types...>& w) noexcept(see below);
Effects: Equivalent to v.swap(w).
Remarks: This function shall not participate in overload resolution unless is_­move_­constructible_­v<T> && is_­swappable_­v<T> is true for all i.
The expression inside noexcept is equivalent to noexcept(v.swap(w)).

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

class bad_variant_access : public exception {
public:
  bad_variant_access() noexcept;
  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.
bad_variant_access() noexcept;
Constructs a bad_­variant_­access object.
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

19.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]).

19.8 Storage for any type [any]

This subclause describes components that C++ programs may use to perform operations on objects of a discriminated type.
[ Note
:
The discriminated type may 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
 ]

19.8.1 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;
}

19.8.2 Class bad_­any_­cast [any.bad_any_cast]

class bad_any_cast : public bad_cast {
public:
  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.
Remarks: The message may be a null-terminated multibyte string ([multibyte.strings]), suitable for conversion and display as a wstring ([string.classes], [locale.codecvt]).

19.8.3 Class any [any.class]

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=(const any& rhs);
    any& operator=(any&& rhs) noexcept;

    template<class T>
      any& operator=(T&& rhs);

    // [any.modifiers], modifiers
    template<class T, class... Args>
      decay_t<T>& emplace(Args&& ...);
    template<class T, class U, class... Args>
      decay_t<T>& emplace(initializer_list<U>, Args&&...);
    void reset() noexcept;
    void swap(any& rhs) noexcept;

    // [any.observers], observers
    bool has_value() const noexcept;
    const type_info& type() const noexcept;
  };
}
An object of class any stores an instance of any type that satisfies the constructor requirements or it has no value, and this is referred to as the state of the class any object.
The stored instance is called the contained value.
Two states are equivalent if either they both have no value, or both have a value and the contained values are equivalent.
The non-member any_­cast functions provide type-safe access to the contained value.
Implementations should avoid the use of dynamically allocated memory for a small contained value.
However, any such small-object optimization shall only be applied to types T for which is_­nothrow_­move_­constructible_­v<T> is true.
[ Example
:
A contained value of type int could be stored in an internal buffer, not in separately-allocated memory.
— end example
 ]

19.8.3.1 Construction and destruction [any.cons]

constexpr any() noexcept;
Ensures: has_­value() is false.
any(const any& other);
Effects: If other.has_­value() is false, constructs an object that has no value.
Otherwise, equivalent to any(in_­place_­type<T>, any_­cast<const T&>(other)) where T is the type of the contained value.
Throws: Any exceptions arising from calling the selected constructor for the contained value.
any(any&& other) noexcept;
Effects: If other.has_­value() is false, constructs an object that has no value.
Otherwise, constructs an object of type any that contains either the contained value of other, or contains an object of the same type constructed from the contained value of other considering that contained value as an rvalue.
Ensures: other is left in a valid but otherwise unspecified state.
template<class T> any(T&& value);