20 General utilities library [utilities]

20.1 General [utilities.general]

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

20.2 Utility components [utility]

20.2.1 Header <utility> synopsis [utility.syn]

The header <utility> contains some basic function and class templates that are used throughout the rest of the library.
#include <compare>              // see [compare.syn]
#include <initializer_list>     // see [initializer.list.syn]

namespace std {
  // [utility.swap], swap
  template<class T>
    constexpr void swap(T& a, T& b) noexcept(see below);
  template<class T, size_t N>
    constexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v<T>);

  // [utility.exchange], exchange
  template<class T, class U = T>
    constexpr T exchange(T& obj, U&& new_val);

  // [forward], forward/move
  template<class T>
    constexpr T&& forward(remove_reference_t<T>& t) noexcept;
  template<class T>
    constexpr T&& forward(remove_reference_t<T>&& t) noexcept;
  template<class T>
    constexpr remove_reference_t<T>&& move(T&&) noexcept;
  template<class T>
    constexpr conditional_t<
        !is_nothrow_move_constructible_v<T> && is_copy_constructible_v<T>, const T&, T&&>
      move_if_noexcept(T& x) noexcept;

  // [utility.as.const], as_­const
  template<class T>
    constexpr add_const_t<T>& as_const(T& t) noexcept;
  template<class T>
    void as_const(const T&&) = delete;

  // [declval], declval
  template<class T>
    add_rvalue_reference_t<T> declval() noexcept;   // as unevaluated operand

  // [utility.intcmp], integer comparison functions
  template<class T, class U>
    constexpr bool cmp_equal(T t, U u) noexcept;
  template<class T, class U>
    constexpr bool cmp_not_equal(T t, U u) noexcept;

  template<class T, class U>
    constexpr bool cmp_less(T t, U u) noexcept;
  template<class T, class U>
    constexpr bool cmp_greater(T t, U u) noexcept;
  template<class T, class U>
    constexpr bool cmp_less_equal(T t, U u) noexcept;
  template<class T, class U>
    constexpr bool cmp_greater_equal(T t, U u) noexcept;

  template<class R, class T>
    constexpr bool in_range(T t) noexcept;

  // [intseq], compile-time integer sequences
\indexlibraryglobal{index_sequence}%
\indexlibraryglobal{make_index_sequence}%
\indexlibraryglobal{index_sequence_for}
  template<class T, T...>
    struct integer_sequence;
  template<size_t... I>
    using index_­sequence = integer_sequence<size_t, I...>;

  template<class T, T N>
    using make_integer_sequence = integer_sequence<T, see below>;
  template<size_t N>
    using make_­index_­sequence = make_integer_sequence<size_t, N>;

  template<class... T>
    using index_­sequence_­for = make_index_sequence<sizeof...(T)>;

  // [pairs], class template pair
  template<class T1, class T2>
    struct pair;

  // [pairs.spec], pair specialized algorithms
  template<class T1, class T2>
    constexpr bool operator==(const pair<T1, T2>&, const pair<T1, T2>&);
  template<class T1, class T2>
    constexpr common_comparison_category_t<synth-three-way-result<T1>,
                                           synth-three-way-result<T2>>
      operator<=>(const pair<T1, T2>&, const pair<T1, T2>&);

  template<class T1, class T2>
    constexpr void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));

  template<class T1, class T2>
    constexpr see below make_pair(T1&&, T2&&);

  // [pair.astuple], tuple-like access to pair
  template<class T> struct tuple_size;
  template<size_t I, class T> struct tuple_element;

  template<class T1, class T2> struct tuple_size<pair<T1, T2>>;
  template<size_t I, class T1, class T2> struct tuple_element<I, pair<T1, T2>>;

  template<size_t I, class T1, class T2>
    constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>&) noexcept;
  template<size_t I, class T1, class T2>
    constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&&) noexcept;
  template<size_t I, class T1, class T2>
    constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>&) noexcept;
  template<size_t I, class T1, class T2>
    constexpr const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&&) noexcept;
  template<class T1, class T2>
    constexpr T1& get(pair<T1, T2>& p) noexcept;
  template<class T1, class T2>
    constexpr const T1& get(const pair<T1, T2>& p) noexcept;
  template<class T1, class T2>
    constexpr T1&& get(pair<T1, T2>&& p) noexcept;
  template<class T1, class T2>
    constexpr const T1&& get(const pair<T1, T2>&& p) noexcept;
  template<class T2, class T1>
    constexpr T2& get(pair<T1, T2>& p) noexcept;
  template<class T2, class T1>
    constexpr const T2& get(const pair<T1, T2>& p) noexcept;
  template<class T2, class T1>
    constexpr T2&& get(pair<T1, T2>&& p) noexcept;
  template<class T2, class T1>
    constexpr const T2&& get(const pair<T1, T2>&& p) noexcept;

  // [pair.piecewise], pair piecewise construction
  struct piecewise_construct_t {
    explicit piecewise_construct_t() = default;
  };
  inline constexpr piecewise_construct_t piecewise_construct{};
  template<class... Types> class tuple;         // defined in <tuple> ([tuple.syn])

  // in-place construction
\indexlibraryglobal{in_place_t}%
\indexlibraryglobal{in_place}%
\indexlibraryglobal{in_place_type_t}%
\indexlibraryglobal{in_place_type}%
\indexlibraryglobal{in_place_index_t}%
\indexlibraryglobal{in_place_index}
  struct in_place_t {
    explicit in_place_t() = default;
  };
  inline constexpr in_place_t in_place{};

  template<class T>
    struct in_place_type_t {
      explicit in_place_type_t() = default;
    };
  template<class T> inline constexpr in_place_type_t<T> in_place_type{};

  template<size_t I>
    struct in_place_index_t {
      explicit in_place_index_t() = default;
    };
  template<size_t I> inline constexpr in_place_index_t<I> in_place_index{};
}

20.2.2 swap [utility.swap]

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

20.2.3 exchange [utility.exchange]

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

20.2.4 Forward/move helpers [forward]

The library provides templated helper functions to simplify applying move semantics to an lvalue and to simplify the implementation of forwarding functions.
All functions specified in this subclause are signal-safe.
template<class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept; template<class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept;
Mandates: For the second overload, is_­lvalue_­reference_­v<T> is false.
Returns: static_­cast<T&&>(t).
Example
:
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).

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

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

20.2.6 Function template declval [declval]

The library provides the function template declval to simplify the definition of expressions which occur as unevaluated operands.
template<class T> add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand
Mandates: This function is not odr-used ([basic.def.odr]).
Remarks: The template parameter T of declval may be an incomplete type.
Example
:
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
 ]

20.2.7 Integer comparison functions [utility.intcmp]

template<class T, class U> constexpr bool cmp_equal(T t, U u) noexcept;
Mandates: Both T and U are standard integer types or extended integer types ([basic.fundamental]).
Effects: Equivalent to:
using UT = make_unsigned_t<T>;
using UU = make_unsigned_t<U>;
if constexpr (is_signed_v<T> == is_signed_v<U>)
  return t == u;
else if constexpr (is_signed_v<T>)
  return t < 0 ? false : UT(t) == u;
else
  return u < 0 ? false : t == UU(u);
template<class T, class U> constexpr bool cmp_not_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_­equal(t, u);
template<class T, class U> constexpr bool cmp_less(T t, U u) noexcept;
Mandates: Both T and U are standard integer types or extended integer types ([basic.fundamental]).
Effects: Equivalent to:
using UT = make_unsigned_t<T>;
using UU = make_unsigned_t<U>;
if constexpr (is_signed_v<T> == is_signed_v<U>)
  return t < u;
else if constexpr (is_signed_v<T>)
  return t < 0 ? true : UT(t) < u;
else
  return u < 0 ? false : t < UU(u);
template<class T, class U> constexpr bool cmp_greater(T t, U u) noexcept;
Effects: Equivalent to: return cmp_­less(u, t);
template<class T, class U> constexpr bool cmp_less_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_­greater(t, u);
template<class T, class U> constexpr bool cmp_greater_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_­less(t, u);
template<class R, class T> constexpr bool in_range(T t) noexcept;
Mandates: Both T and R are standard integer types or extended integer types ([basic.fundamental]).
Effects: Equivalent to:
return cmp_greater_equal(t, numeric_limits<R>::min()) &&
       cmp_less_equal(t, numeric_limits<R>::max());
Note
:
These function templates cannot be used to compare byte, char, char8_­t, char16_­t, char32_­t, wchar_­t, and bool.
— end note
 ]

20.3 Compile-time integer sequences [intseq]

20.3.1 In general [intseq.general]

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

20.3.2 Class template integer_­sequence [intseq.intseq]

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

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

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

20.4 Pairs [pairs]

20.4.1 In general [pairs.general]

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

20.4.2 Class template pair [pairs.pair]

namespace std {
  template<class T1, class T2>
  struct pair {
    using first_type  = T1;
    using second_type = T2;

    T1 first;
    T2 second;

    pair(const pair&) = default;
    pair(pair&&) = default;
    constexpr explicit(see below) pair();
    constexpr explicit(see below) pair(const T1& x, const T2& y);
    template<class U1, class U2>
      constexpr explicit(see below) pair(U1&& x, U2&& y);
    template<class U1, class U2>
      constexpr explicit(see below) pair(const pair<U1, U2>& p);
    template<class U1, class U2>
      constexpr explicit(see below) pair(pair<U1, U2>&& p);
    template<class... Args1, class... Args2>
      constexpr pair(piecewise_construct_t,
                     tuple<Args1...> first_args, tuple<Args2...> second_args);

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

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

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

20.4.3 Specialized algorithms [pairs.spec]

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

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

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

20.4.5 Piecewise construction [pair.piecewise]

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

20.5 Tuples [tuple]

20.5.1 In general [tuple.general]

Subclause [tuple] describes the tuple library that provides a tuple type as the class template tuple that can be instantiated with any number of arguments.
Each template argument specifies the type of an element in the tuple.
Consequently, tuples are heterogeneous, fixed-size collections of values.
An instantiation of tuple with two arguments is similar to an instantiation of pair with the same two arguments.

20.5.2 Header <tuple> synopsis [tuple.syn]

#include <compare>              // see [compare.syn]

namespace std {
  // [tuple.tuple], class template tuple
  template<class... Types>
    class tuple;

  // [tuple.creation], tuple creation functions
  inline constexpr unspecified ignore;

  template<class... TTypes>
    constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&...);

  template<class... TTypes>
    constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&...) noexcept;

  template<class... TTypes>
    constexpr tuple<TTypes&...> tie(TTypes&...) noexcept;

  template<class... Tuples>
    constexpr tuple<CTypes...> tuple_cat(Tuples&&...);

  // [tuple.apply], calling a function with a tuple of arguments
  template<class F, class Tuple>
    constexpr decltype(auto) apply(F&& f, Tuple&& t);

  template<class T, class Tuple>
    constexpr T make_from_tuple(Tuple&& t);

  // [tuple.helper], tuple helper classes
  template<class T> struct tuple_size;                  // not defined
  template<class T> struct tuple_size<const T>;

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

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

  template<size_t I, class... Types>
    struct tuple_element<I, tuple<Types...>>;

  template<size_t I, class T>
    using tuple_element_t = typename tuple_element<I, T>::type;

  // [tuple.elem], element access
  template<size_t I, class... Types>
    constexpr tuple_element_t<I, tuple<Types...>>& get(tuple<Types...>&) noexcept;
  template<size_t I, class... Types>
    constexpr tuple_element_t<I, tuple<Types...>>&& get(tuple<Types...>&&) noexcept;
  template<size_t I, class... Types>
    constexpr const tuple_element_t<I, tuple<Types...>>& get(const tuple<Types...>&) noexcept;
  template<size_t I, class... Types>
    constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&&) noexcept;
  template<class T, class... Types>
    constexpr T& get(tuple<Types...>& t) noexcept;
  template<class T, class... Types>
    constexpr T&& get(tuple<Types...>&& t) noexcept;
  template<class T, class... Types>
    constexpr const T& get(const tuple<Types...>& t) noexcept;
  template<class T, class... Types>
    constexpr const T&& get(const tuple<Types...>&& t) noexcept;

  // [tuple.rel], relational operators
  template<class... TTypes, class... UTypes>
    constexpr bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&);
  template<class... TTypes, class... UTypes>
    constexpr common_comparison_category_t<synth-three-way-result<TTypes, UTypes>...>
      operator<=>(const tuple<TTypes...>&, const tuple<UTypes...>&);

  // [tuple.traits], allocator-related traits
  template<class... Types, class Alloc>
    struct uses_allocator<tuple<Types...>, Alloc>;

  // [tuple.special], specialized algorithms
  template<class... Types>
    constexpr void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);

  // [tuple.helper], tuple helper classes
  template<class T>
    inline constexpr size_t tuple_size_v = tuple_size<T>::value;
}

20.5.3 Class template tuple [tuple.tuple]

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

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

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

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

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

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

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

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

    // [tuple.swap], tuple swap
    constexpr void swap(tuple&) noexcept(see below);
  };

  template<class... UTypes>
    tuple(UTypes...) -> tuple<UTypes...>;
  template<class T1, class T2>
    tuple(pair<T1, T2>) -> tuple<T1, T2>;
  template<class Alloc, class... UTypes>
    tuple(allocator_arg_t, Alloc, UTypes...) -> tuple<UTypes...>;
  template<class Alloc, class T1, class T2>
    tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>;
  template<class Alloc, class... UTypes>
    tuple(allocator_arg_t, Alloc, tuple<UTypes...>) -> tuple<UTypes...>;
}

20.5.3.1 Construction [tuple.cnstr]

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

20.5.3.2 Assignment [tuple.assign]

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

20.5.3.3 swap [tuple.swap]

constexpr void swap(tuple& rhs) noexcept(see below);
Preconditions: Each element in *this is swappable with ([swappable.requirements]) the corresponding element in rhs.
Effects: Calls swap for each element in *this and its corresponding element in rhs.
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.

20.5.4 Tuple creation functions [tuple.creation]

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

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

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

20.5.6 Tuple helper classes [tuple.helper]

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

20.5.7 Element access [tuple.elem]

template<size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>& get(tuple<Types...>& t) noexcept; template<size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>&& get(tuple<Types...>&& t) noexcept; // Note A template<size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>& get(const tuple<Types...>& t) noexcept; // Note B template<size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
Mandates: .
Returns: A reference to the element of t, where indexing is zero-based.
Note A
:
If a type T in Types is some reference type X&, the return type is X&, not X&&.
However, if the element type is a non-reference type T, the return type is T&&.
— end note
 ]
Note B
:
Constness is shallow.
If a type T in Types is some reference type X&, the return type is X&, not const X&.
However, if the element type is a non-reference type T, the return type is const T&.
This is consistent with how constness is defined to work for member variables of reference type.
— end note
 ]
template<class T, class... Types> constexpr T& get(tuple<Types...>& t) noexcept; template<class T, class... Types> constexpr T&& get(tuple<Types...>&& t) noexcept; template<class T, class... Types> constexpr const T& get(const tuple<Types...>& t) noexcept; template<class T, class... Types> constexpr const T&& get(const tuple<Types...>&& t) noexcept;
Mandates: The type T occurs exactly once in Types.
Returns: A reference to the element of t corresponding to the type T in Types.
Example
:
const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6);
const int& i1 = get<int>(t);                    // OK, i1 has value 1
const int& i2 = get<const int>(t);              // OK, i2 has value 2
const double& d = get<double>(t);               // error: type double is not unique within t
— end example
 ]
Note
:
The reason get is a non-member function is that if this functionality had been provided as a member function, code where the type depended on a template parameter would have required using the template keyword.
— end note
 ]

20.5.8 Relational operators [tuple.rel]

template<class... TTypes, class... UTypes> constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Mandates: For all i, where , get<i>(t) == get<i>(u) is a valid expression returning a type that is convertible to bool.
sizeof...(TTypes) equals sizeof...(UTypes).
Returns: true if get<i>(t) == get<i>(u) for all i, otherwise false.
For any two zero-length tuples e and f, e == f returns true.
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 common_comparison_category_t<synth-three-way-result<TTypes, UTypes>...> operator<=>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Effects: Performs a lexicographical comparison between t and u.
For any two zero-length tuples t and u, t <=> u returns strong_­ordering​::​equal.
Otherwise, equivalent to:
if (auto c = synth-three-way(get<0>(t), get<0>(u)); c != 0) return c;
return  <=> ;
where for some tuple r is a tuple containing all but the first element of r.
Note
:
The above definition does 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
 ]

20.5.9 Tuple traits [tuple.traits]

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

20.5.10 Tuple specialized algorithms [tuple.special]

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

20.6 Optional objects [optional]

20.6.1 In general [optional.general]

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

20.6.2 Header <optional> synopsis [optional.syn]

#include <compare>              // see [compare.syn]

namespace std {
  // [optional.optional], class template optional
  template<class T>
    class optional;

  // [optional.nullopt], no-value state indicator
  struct nullopt_t{see below};
  inline constexpr nullopt_t nullopt(unspecified);

  // [optional.bad.access], class bad_­optional_­access
  class bad_optional_access;

  // [optional.relops], relational operators
  template<class T, class U>
    constexpr bool operator==(const optional<T>&, const optional<U>&);
  template<class T, class U>
    constexpr bool operator!=(const optional<T>&, const optional<U>&);
  template<class T, class U>
    constexpr bool operator<(const optional<T>&, const optional<U>&);
  template<class T, class U>
    constexpr bool operator>(const optional<T>&, const optional<U>&);
  template<class T, class U>
    constexpr bool operator<=(const optional<T>&, const optional<U>&);
  template<class T, class U>
    constexpr bool operator>=(const optional<T>&, const optional<U>&);
  template<class T, three_way_comparable_with<T> U>
    constexpr compare_three_way_result_t<T,U>
      operator<=>(const optional<T>&, const optional<U>&);

  // [optional.nullops], comparison with nullopt
  template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
  template<class T>
    constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept;

  // [optional.comp.with.t], comparison with T
  template<class T, class U> constexpr bool operator==(const optional<T>&, const U&);
  template<class T, class U> constexpr bool operator==(const T&, const optional<U>&);
  template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
  template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
  template<class T, class U> constexpr bool operator<(const optional<T>&, const U&);
  template<class T, class U> constexpr bool operator<(const T&, const optional<U>&);
  template<class T, class U> constexpr bool operator>(const optional<T>&, const U&);
  template<class T, class U> constexpr bool operator>(const T&, const optional<U>&);
  template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
  template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
  template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
  template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
  template<class T, three_way_comparable_with<T> U>
    constexpr compare_three_way_result_t<T,U>
      operator<=>(const optional<T>&, const U&);

  // [optional.specalg], specialized algorithms
  template<class T>
    void swap(optional<T>&, optional<T>&) noexcept(see below);

  template<class T>
    constexpr optional<see below> make_optional(T&&);
  template<class T, class... Args>
    constexpr optional<T> make_optional(Args&&... args);
  template<class T, class U, class... Args>
    constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);

  // [optional.hash], hash support
  template<class T> struct hash;
  template<class T> struct hash<optional<T>>;
}

20.6.3 Class template optional [optional.optional]

namespace std {
  template<class T>
  class optional {
  public:
    using value_type = T;

    // [optional.ctor], constructors
    constexpr optional() noexcept;
    constexpr optional(nullopt_t) noexcept;
    constexpr optional(const optional&);
    constexpr optional(optional&&) noexcept(see below);
    template<class... Args>
      constexpr explicit optional(in_place_t, Args&&...);
    template<class U, class... Args>
      constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...);
    template<class U = T>
      constexpr explicit(see below) optional(U&&);
    template<class U>
      explicit(see below) optional(const optional<U>&);
    template<class U>
      explicit(see below) optional(optional<U>&&);

    // [optional.dtor], destructor
    ~optional();

    // [optional.assign], assignment
    optional& operator=(nullopt_t) noexcept;
    constexpr optional& operator=(const optional&);
    constexpr optional& operator=(optional&&) noexcept(see below);
    template<class U = T> optional& operator=(U&&);
    template<class U> optional& operator=(const optional<U>&);
    template<class U> optional& operator=(optional<U>&&);
    template<class... Args> T& emplace(Args&&...);
    template<class U, class... Args> T& emplace(initializer_list<U>, Args&&...);

    // [optional.swap], swap
    void swap(optional&) noexcept(see below);

    // [optional.observe], observers
    constexpr const T* operator->() const;
    constexpr T* operator->();
    constexpr const T& operator*() const&;
    constexpr T& operator*() &;
    constexpr T&& operator*() &&;
    constexpr const T&& operator*() const&&;
    constexpr explicit operator bool() const noexcept;
    constexpr bool has_value() const noexcept;
    constexpr const T& value() const&;
    constexpr T& value() &;
    constexpr T&& value() &&;
    constexpr const T&& value() const&&;
    template<class U> constexpr T value_or(U&&) const&;
    template<class U> constexpr T value_or(U&&) &&;

    // [optional.mod], modifiers
    void reset() noexcept;

  private:
    T *val;         // exposition only
  };

  template<class T>
    optional(T) -> optional<T>;
}
Any instance of optional<T> at any given time either contains a value or does not contain a value.
When an instance of optional<T> contains a value, it means that an object of type T, referred to as the optional object's contained value, is allocated within the storage of the optional object.
Implementations are not permitted to use additional storage, such as dynamic memory, to allocate its contained value.
The contained value shall be allocated in a region of the optional<T> storage suitably aligned for the type T.
When an object of type optional<T> is contextually converted to bool, the conversion returns true if the object contains a value; otherwise the conversion returns false.
Member val is provided for exposition only.
When an optional<T> object contains a value, val points to the contained value.
T shall be a type other than cv in_­place_­t or cv nullopt_­t that meets the Cpp17Destructible requirements (Table 32).

20.6.3.1 Constructors [optional.ctor]

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

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

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

20.6.3.4 Swap [optional.swap]

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

20.6.3.5 Observers [optional.observe]

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

20.6.3.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.
Postconditions: *this does not contain a value.

20.6.4 No-value state indicator [optional.nullopt]

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

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

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

20.6.6 Relational operators [optional.relops]

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

20.6.7 Comparison with nullopt [optional.nullops]

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

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

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

20.6.9 Specialized algorithms [optional.specalg]

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

20.6.10 Hash support [optional.hash]

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

20.7 Variants [variant]

20.7.1 In general [variant.general]

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

20.7.2 Header <variant> synopsis [variant.syn]

#include <compare>              // see [compare.syn]

namespace std {
  // [variant.variant], class template variant
  template<class... Types>
    class variant;

  // [variant.helper], variant helper classes
  template<class T> struct variant_size;                        // not defined
  template<class T> struct variant_size<const T>;
  template<class T>
    inline constexpr size_t variant_size_v = variant_size<T>::value;

  template<class... Types>
    struct variant_size<variant<Types...>>;

  template<size_t I, class T> struct variant_alternative;       // not defined
  template<size_t I, class T> struct variant_alternative<I, const T>;
  template<size_t I, class T>
    using variant_alternative_t = typename variant_alternative<I, T>::type;

  template<size_t I, class... Types>
    struct variant_alternative<I, variant<Types...>>;

  inline constexpr size_t variant_npos = -1;

  // [variant.get], value access
  template<class T, class... Types>
    constexpr bool holds_alternative(const variant<Types...>&) noexcept;

  template<size_t I, class... Types>
    constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>&);
  template<size_t I, class... Types>
    constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&&);
  template<size_t I, class... Types>
    constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>&);
  template<size_t I, class... Types>
    constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&&);

  template<class T, class... Types>
    constexpr T& get(variant<Types...>&);
  template<class T, class... Types>
    constexpr T&& get(variant<Types...>&&);
  template<class T, class... Types>
    constexpr const T& get(const variant<Types...>&);
  template<class T, class... Types>
    constexpr const T&& get(const variant<Types...>&&);

  template<size_t I, class... Types>
    constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
      get_if(variant<Types...>*) noexcept;
  template<size_t I, class... Types>
    constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
      get_if(const variant<Types...>*) noexcept;

  template<class T, class... Types>
    constexpr add_pointer_t<T>
      get_if(variant<Types...>*) noexcept;
  template<class T, class... Types>
    constexpr add_pointer_t<const T>
      get_if(const variant<Types...>*) noexcept;

  // [variant.relops], relational operators
  template<class... Types>
    constexpr bool operator==(const variant<Types...>&, const variant<Types...>&);
  template<class... Types>
    constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&);
  template<class... Types>
    constexpr bool operator<(const variant<Types...>&, const variant<Types...>&);
  template<class... Types>
    constexpr bool operator>(const variant<Types...>&, const variant<Types...>&);
  template<class... Types>
    constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&);
  template<class... Types>
    constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&);
  template<class... Types> requires (three_way_comparable<Types> && ...)
    constexpr common_comparison_category_t<compare_three_way_result_t<Types>...>
      operator<=>(const variant<Types...>&, const variant<Types...>&);

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

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

  // [variant.monostate.relops], monostate relational operators
  constexpr bool operator==(monostate, monostate) noexcept;
  constexpr strong_ordering operator<=>(monostate, monostate) noexcept;

  // [variant.specalg], specialized algorithms
  template<class... Types>
    void swap(variant<Types...>&, variant<Types...>&) noexcept(see below);

  // [variant.bad.access], class bad_­variant_­access
  class bad_variant_access;

  // [variant.hash], hash support
  template<class T> struct hash;
  template<class... Types> struct hash<variant<Types...>>;
  template<> struct hash<monostate>;
}

20.7.3 Class template variant [variant.variant]

namespace std {
  template<class... Types>
  class variant {
  public:
    // [variant.ctor], constructors
    constexpr variant() noexcept(see below);
    constexpr variant(const variant&);
    constexpr variant(variant&&) noexcept(see below);

    template<class T>
      constexpr variant(T&&) noexcept(see below);

    template<class T, class... Args>
      constexpr explicit variant(in_place_type_t<T>, Args&&...);
    template<class T, class U, class... Args>
      constexpr explicit variant(in_place_type_t<T>, initializer_list<U>, Args&&...);

    template<size_t I, class... Args>
      constexpr explicit variant(in_place_index_t<I>, Args&&...);
    template<size_t I, class U, class... Args>
      constexpr explicit variant(in_place_index_t<I>, initializer_list<U>, Args&&...);

    // [variant.dtor], destructor
    ~variant();

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

    template<class T> variant& operator=(T&&) noexcept(see below);

    // [variant.mod], modifiers
    template<class T, class... Args>
      T& emplace(Args&&...);
    template<class T, class U, class... Args>
      T& emplace(initializer_list<U>, Args&&...);
    template<size_t I, class... Args>
      variant_alternative_t<I, variant<Types...>>& emplace(Args&&...);
    template<size_t I, class U, class... Args>
      variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U>, Args&&...);

    // [variant.status], value status
    constexpr bool valueless_by_exception() const noexcept;
    constexpr size_t index() const noexcept;

    // [variant.swap], swap
    void swap(variant&) noexcept(see below);
  };
}
Any instance of variant at any given time either holds a value of one of its alternative types or holds no value.
When an instance of variant holds a value of alternative type T, it means that a value of type T, referred to as the variant object's contained value, is allocated within the storage of the variant object.
Implementations are not permitted to use additional storage, such as dynamic memory, to allocate the contained value.
The contained value shall be allocated in a region of the variant storage suitably aligned for all types in Types.
All types in Types shall meet the Cpp17Destructible requirements (Table 32).
A program that instantiates the definition of variant with no template arguments is ill-formed.

20.7.3.1 Constructors [variant.ctor]

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

20.7.3.2 Destructor [variant.dtor]

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

20.7.3.3 Assignment [variant.assign]

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

20.7.3.4 Modifiers [variant.mod]

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

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

20.7.3.6 Swap [variant.swap]

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

20.7.4 variant helper classes [variant.helper]

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

20.7.5 Value access [variant.get]

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

20.7.6 Relational operators [variant.relops]

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

20.7.7 Visitation [variant.visit]

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

20.7.8 Class monostate [variant.monostate]

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

20.7.9 monostate relational operators [variant.monostate.relops]

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

20.7.10 Specialized algorithms [variant.specalg]

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

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

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

20.7.12 Hash support [variant.hash]

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

20.8 Storage for any type [any]

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
 ]

20.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;
}

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

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

20.8.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 meets 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 they 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
 ]

20.8.3.1 Construction and destruction [any.cons]

constexpr any() noexcept;
Postconditions: 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.
template<class T> any(T&& value);
Let VT be decay_­t<T>.
Constraints: VT is not the same type as any, VT is not a specialization of in_­place_­type_­t, and is_­copy_­constructible_­v<VT> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Constructs an object of type any that contains an object of type VT direct-initialized with std​::​forward<T>(value).
Throws: Any exception thrown by the selected constructor of VT.
template<class T, class... Args> explicit any(in_place_type_t<T>, Args&&... args);
Let VT be decay_­t<T>.
Constraints: is_­copy_­constructible_­v<VT> is true and is_­constructible_­v<VT, Args...> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Initializes the contained value as if direct-non-list-initializing an object of type VT with the arguments std​::​forward<Args>(args)....
Postconditions: *this contains a value of type VT.
Throws: Any exception thrown by the selected constructor of VT.
template<class T, class U, class... Args> explicit any(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Let VT be decay_­t<T>.
Constraints: is_­copy_­constructible_­v<VT> is true and is_­constructible_­v<VT, initializer_­list<U>&, Args...> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Initializes the contained value as if direct-non-list-initializing an object of type VT with the arguments il, std​::​forward<Args>(args)....
Postconditions: *this contains a value.
Throws: Any exception thrown by the selected constructor of VT.
~any();
Effects: As if by reset().

20.8.3.2 Assignment [any.assign]

any& operator=(const any& rhs);
Effects: As if by any(rhs).swap(*this).
No effects if an exception is thrown.
Returns: *this.
Throws: Any exceptions arising from the copy constructor for the contained value.
any& operator=(any&& rhs) noexcept;
Effects: As if by any(std​::​move(rhs)).swap(*this).
Returns: *this.
Postconditions: The state of *this is equivalent to the original state of rhs.
template<class T> any& operator=(T&& rhs);
Let VT be decay_­t<T>.
Constraints: VT is not the same type as any and is_­copy_­constructible_­v<VT> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Constructs an object tmp of type any that contains an object of type VT direct-initialized with std​::​forward<T>(rhs), and tmp.swap(*this).
No effects if an exception is thrown.
Returns: *this.
Throws: Any exception thrown by the selected constructor of VT.

20.8.3.3 Modifiers [any.modifiers]

template<class T, class... Args> decay_t<T>& emplace(Args&&... args);
Let VT be decay_­t<T>.
Constraints: is_­copy_­constructible_­v<VT> is true and is_­constructible_­v<VT, Args...> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Calls reset().
Then initializes the contained value as if direct-non-list-initializing an object of type VT with the arguments std​::​forward<Args>(args)....
Postconditions: *this contains a value.
Returns: A reference to the new contained value.
Throws: Any exception thrown by the selected constructor of VT.
Remarks: If an exception is thrown during the call to VT's constructor, *this does not contain a value, and any previously contained value has been destroyed.
template<class T, class U, class... Args> decay_t<T>& emplace(initializer_list<U> il, Args&&... args);
Let VT be decay_­t<T>.
Constraints: is_­copy_­constructible_­v<VT> is true and is_­constructible_­v<VT, initializer_­list<U>&, Args...> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Calls reset().
Then initializes the contained value as if direct-non-list-initializing an object of type VT with the arguments il, std​::​forward<Args>(args)....
Postconditions: *this contains a value.
Returns: A reference to the new contained value.
Throws: Any exception thrown by the selected constructor of VT.
Remarks: If an exception is thrown during the call to VT's constructor, *this does not contain a value, and any previously contained value has been destroyed.
void reset() noexcept;
Effects: If has_­value() is true, destroys the contained value.
Postconditions: has_­value() is false.
void swap(any& rhs) noexcept;
Effects: Exchanges the states of *this and rhs.

20.8.3.4 Observers [any.observers]

bool has_value() const noexcept;
Returns: true if *this contains an object, otherwise false.
const type_info& type() const noexcept;
Returns: typeid(T) if *this has a contained value of type T, otherwise typeid(void).
Note
:
Useful for querying against types known either at compile time or only at runtime.
— end note
 ]

20.8.4 Non-member functions [any.nonmembers]

void swap(any& x, any& y) noexcept;
Effects: Equivalent to x.swap(y).
template<class T, class... Args> any make_any(Args&&... args);
Effects: Equivalent to: return any(in_­place_­type<T>, std​::​forward<Args>(args)...);
template<class T, class U, class... Args> any make_any(initializer_list<U> il, Args&&... args);
Effects: Equivalent to: return any(in_­place_­type<T>, il, std​::​forward<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);
Let U be the type remove_­cvref_­t<T>.
Mandates: For the first overload, is_­constructible_­v<T, const U&> is true.
For the second overload, is_­constructible_­v<T, U&> is true.
For the third overload, is_­constructible_­v<T, U> is true.
Returns: For the first and second overload, static_­cast<T>(*any_­cast<U>(&operand)).
For the third overload, static_­cast<T>(std​::​move(*any_­cast<U>(&operand))).
Throws: bad_­any_­cast if operand.type() != typeid(remove_­reference_­t<T>).
Example
:
any x(5);                                   // x holds int
assert(any_cast<int>(x) == 5);              // cast to value
any_cast<int&>(x) = 10;                     // cast to reference
assert(any_cast<int>(x) == 10);

x = "Meow";                                 // x holds const char*
assert(strcmp(any_cast<const char*>(x), "Meow") == 0);
any_cast<const char*&>(x) = "Harry";
assert(strcmp(any_cast<const char*>(x), "Harry") == 0);

x = string("Meow");                         // x holds string
string s, s2("Jane");
s = move(any_cast<string&>(x));             // move from any
assert(s == "Meow");
any_cast<string&>(x) = move(s2);            // move to any
assert(any_cast<const string&>(x) == "Jane");

string cat("Meow");
const any y(cat);                           // const y holds string
assert(any_cast<const string&>(y) == cat);

any_cast<string&>(y);                       // error: cannot any_­cast away const
— end example
 ]
template<class T> const T* any_cast(const any* operand) noexcept; template<class T> T* any_cast(any* operand) noexcept;
Returns: If operand != nullptr && operand->type() == typeid(T), a pointer to the object contained by operand; otherwise, nullptr.
Example
:
bool is_string(const any& operand) {
  return any_cast<string>(&operand) != nullptr;
}
— end example
 ]

20.9 Bitsets [bitset]

20.9.1 Header <bitset> synopsis [bitset.syn]

The header <bitset> defines a class template and several related functions for representing and manipulating fixed-size sequences of bits.
#include <string>
#include <iosfwd>   // for istream, ostream, see [iosfwd.syn]

namespace std {
  template<size_t N> class bitset;

  // [bitset.operators], bitset operators
  template<size_t N>
    bitset<N> operator&(const bitset<N>&, const bitset<N>&) noexcept;
  template<size_t N>
    bitset<N> operator|(const bitset<N>&, const bitset<N>&) noexcept;
  template<size_t N>
    bitset<N> operator^(const bitset<N>&, const bitset<N>&) noexcept;
  template<class charT, class traits, size_t N>
    basic_istream<charT, traits>&
      operator>>(basic_istream<charT, traits>& is, bitset<N>& x);
  template<class charT, class traits, size_t N>
    basic_ostream<charT, traits>&
      operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x);
}

20.9.2 Class template bitset [template.bitset]

namespace std {
  template<size_t N> class bitset {
  public:
    // bit reference
    class reference {
      friend class bitset;
      reference() noexcept;

    public:
      reference(const reference&) = default;
      ~reference();
      reference& operator=(bool x) noexcept;            // for b[i] = x;
      reference& operator=(const reference&) noexcept;  // for b[i] = b[j];
      bool operator~() const noexcept;                  // flips the bit
      operator bool() const noexcept;                   // for x = b[i];
      reference& flip() noexcept;                       // for b[i].flip();
    };

    // [bitset.cons], constructors
    constexpr bitset() noexcept;
    constexpr bitset(unsigned long long val) noexcept;
    template<class charT, class traits, class Allocator>
      explicit bitset(
        const basic_string<charT, traits, Allocator>& str,
        typename basic_string<charT, traits, Allocator>::size_type pos = 0,
        typename basic_string<charT, traits, Allocator>::size_type n
          = basic_string<charT, traits, Allocator>::npos,
        charT zero = charT('0'),
        charT one = charT('1'));
    template<class charT>
      explicit bitset(
        const charT* str,
        typename basic_string<charT>::size_type n = basic_string<charT>::npos,
        charT zero = charT('0'),
        charT one = charT('1'));

    // [bitset.members], bitset operations
    bitset<N>& operator&=(const bitset<N>& rhs) noexcept;
    bitset<N>& operator|=(const bitset<N>& rhs) noexcept;
    bitset<N>& operator^=(const bitset<N>& rhs) noexcept;
    bitset<N>& operator<<=(size_t pos) noexcept;
    bitset<N>& operator>>=(size_t pos) noexcept;
    bitset<N>& set() noexcept;
    bitset<N>& set(size_t pos, bool val = true);
    bitset<N>& reset() noexcept;
    bitset<N>& reset(size_t pos);
    bitset<N>  operator~() const noexcept;
    bitset<N>& flip() noexcept;
    bitset<N>& flip(size_t pos);

    // element access
    constexpr bool operator[](size_t pos) const;        // for b[i];
    reference operator[](size_t pos);                   // for b[i];

    unsigned long to_ulong() const;
    unsigned long long to_ullong() const;
    template<class charT = char,
             class traits = char_traits<charT>,
             class Allocator = allocator<charT>>
      basic_string<charT, traits, Allocator>
        to_string(charT zero = charT('0'), charT one = charT('1')) const;

    size_t count() const noexcept;
    constexpr size_t size() const noexcept;
    bool operator==(const bitset<N>& rhs) const noexcept;
    bool test(size_t pos) const;
    bool all() const noexcept;
    bool any() const noexcept;
    bool none() const noexcept;
    bitset<N> operator<<(size_t pos) const noexcept;
    bitset<N> operator>>(size_t pos) const noexcept;
  };

  // [bitset.hash], hash support
  template<class T> struct hash;
  template<size_t N> struct hash<bitset<N>>;
}
The class template bitset<N> describes an object that can store a sequence consisting of a fixed number of bits, N.
Each bit represents either the value zero (reset) or one (set).
To toggle a bit is to change the value zero to one, or the value one to zero.
Each bit has a non-negative position pos.
When converting between an object of class bitset<N> and a value of some integral type, bit position pos corresponds to the bit value 1 << pos.
The integral value corresponding to two or more bits is the sum of their bit values.
The functions described in this subclause can report three kinds of errors, each associated with a distinct exception:

20.9.2.1 Constructors [bitset.cons]

constexpr bitset() noexcept;
Effects: Initializes all bits in *this to zero.
constexpr bitset(unsigned long long val) noexcept;
Effects: Initializes the first M bit positions to the corresponding bit values in val.
M is the smaller of N and the number of bits in the value representation of unsigned long long.
If M < N, the remaining bit positions are initialized to zero.
template<class charT, class traits, class Allocator> explicit bitset( const basic_string<charT, traits, Allocator>& str, typename basic_string<charT, traits, Allocator>::size_type pos = 0, typename basic_string<charT, traits, Allocator>::size_type n = basic_string<charT, traits, Allocator>::npos, charT zero = charT('0'), charT one = charT('1'));
Effects: Determines the effective length rlen of the initializing string as the smaller of n and str.size() - pos.
Initializes the first M bit positions to values determined from the corresponding characters in the string str.
M is the smaller of N and rlen.
An element of the constructed object has value zero if the corresponding character in str, beginning at position pos, is zero.
Otherwise, the element has the value one.
Character position pos + M - 1 corresponds to bit position zero.
Subsequent decreasing character positions correspond to increasing bit positions.
If M < N, remaining bit positions are initialized to zero.
The function uses traits​::​eq to compare the character values.
Throws: out_­of_­range if pos > str.size() or invalid_­argument if any of the rlen characters in str beginning at position pos is other than zero or one.
template<class charT> explicit bitset( const charT* str, typename basic_string<charT>::size_type n = basic_string<charT>::npos, charT zero = charT('0'), charT one = charT('1'));
Effects: As if by:
bitset(n == basic_string<charT>::npos
          ? basic_string<charT>(str)
          : basic_string<charT>(str, n),
       0, n, zero, one)

20.9.2.2 Members [bitset.members]

bitset<N>& operator&=(const bitset<N>& rhs) noexcept;
Effects: Clears each bit in *this for which the corresponding bit in rhs is clear, and leaves all other bits unchanged.
Returns: *this.
bitset<N>& operator|=(const bitset<N>& rhs) noexcept;
Effects: Sets each bit in *this for which the corresponding bit in rhs is set, and leaves all other bits unchanged.
Returns: *this.
bitset<N>& operator^=(const bitset<N>& rhs) noexcept;
Effects: Toggles each bit in *this for which the corresponding bit in rhs is set, and leaves all other bits unchanged.
Returns: *this.
bitset<N>& operator<<=(size_t pos) noexcept;
Effects: Replaces each bit at position I in *this with a value determined as follows:
  • If I < pos, the new value is zero;
  • If I >= pos, the new value is the previous value of the bit at position I - pos.
Returns: *this.
bitset<N>& operator>>=(size_t pos) noexcept;
Effects: Replaces each bit at position I in *this with a value determined as follows:
  • If pos >= N - I, the new value is zero;
  • If pos < N - I, the new value is the previous value of the bit at position I + pos.
Returns: *this.
bitset<N>& set() noexcept;
Effects: Sets all bits in *this.
Returns: *this.
bitset<N>& set(size_t pos, bool val = true);
Effects: Stores a new value in the bit at position pos in *this.
If val is true, the stored value is one, otherwise it is zero.
Returns: *this.
Throws: out_­of_­range if pos does not correspond to a valid bit position.
bitset<N>& reset() noexcept;
Effects: Resets all bits in *this.
Returns: *this.
bitset<N>& reset(size_t pos);
Effects: Resets the bit at position pos in *this.
Returns: *this.
Throws: out_­of_­range if pos does not correspond to a valid bit position.
bitset<N> operator~() const noexcept;
Effects: Constructs an object x of class bitset<N> and initializes it with *this.
Returns: x.flip().
bitset<N>& flip() noexcept;
Effects: Toggles all bits in *this.
Returns: *this.
bitset<N>& flip(size_t pos);
Effects: Toggles the bit at position pos in *this.
Returns: *this.
Throws: out_­of_­range if pos does not correspond to a valid bit position.
unsigned long to_ulong() const;
Returns: x.
Throws: overflow_­error if the integral value x corresponding to the bits in *this cannot be represented as type unsigned long.
unsigned long long to_ullong() const;
Returns: x.
Throws: overflow_­error if the integral value x corresponding to the bits in *this cannot be represented as type unsigned long long.
template<class charT = char, class traits = char_traits<charT>, class Allocator = allocator<charT>> basic_string<charT, traits, Allocator> to_string(charT zero = charT('0'), charT one = charT('1')) const;
Effects: Constructs a string object of the appropriate type and initializes it to a string of length N characters.
Each character is determined by the value of its corresponding bit position in *this.
Character position N - 1 corresponds to bit position zero.
Subsequent decreasing character positions correspond to increasing bit positions.
Bit value zero becomes the character zero, bit value one becomes the character one.
Returns: The created object.
size_t count() const noexcept;
Returns: A count of the number of bits set in *this.
constexpr size_t size() const noexcept;
Returns: N.
bool operator==(const bitset<N>& rhs) const noexcept;
Returns: true if the value of each bit in *this equals the value of the corresponding bit in rhs.
bool test(size_t pos) const;
Returns: true if the bit at position pos in *this has the value one.
Throws: out_­of_­range if pos does not correspond to a valid bit position.
bool all() const noexcept;
Returns: count() == size().
bool any() const noexcept;
Returns: count() != 0.
bool none() const noexcept;
Returns: count() == 0.
bitset<N> operator<<(size_t pos) const noexcept;
Returns: bitset<N>(*this) <<= pos.
bitset<N> operator>>(size_t pos) const noexcept;
Returns: bitset<N>(*this) >>= pos.
constexpr bool operator[](size_t pos) const;
Preconditions: pos is valid.
Returns: true if the bit at position pos in *this has the value one, otherwise false.
Throws: Nothing.
bitset<N>::reference operator[](size_t pos);
Preconditions: pos is valid.
Returns: An object of type bitset<N>​::​reference such that (*this)[pos] == this->test(pos), and such that (*this)[pos] = val is equivalent to this->set(pos, val).
Throws: Nothing.
Remarks: For the purpose of determining the presence of a data race, any access or update through the resulting reference potentially accesses or modifies, respectively, the entire underlying bitset.

20.9.3 bitset hash support [bitset.hash]

template<size_t N> struct hash<bitset<N>>;
The specialization is enabled ([unord.hash]).

20.9.4 bitset operators [bitset.operators]

bitset<N> operator&(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
Returns: bitset<N>(lhs) &= rhs.
bitset<N> operator|(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
Returns: bitset<N>(lhs) |= rhs.
bitset<N> operator^(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
Returns: bitset<N>(lhs) ^= rhs.
template<class charT, class traits, size_t N> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, bitset<N>& x);
Effects: Extracts up to N characters from is.
Stores these characters in a temporary object str of type basic_­string<charT, traits>, then evaluates the expression x = bitset<N>(str).
Characters are extracted and stored until any of the following occurs:
  • N characters have been extracted and stored;
  • end-of-file occurs on the input sequence;
  • the next input character is neither is.widen('0') nor is.widen('1') (in which case the input character is not extracted).
If N > 0 and no characters are stored in str, calls is.setstate(ios_­base​::​failbit) (which may throw ios_­base​::​failure ([iostate.flags])).
Returns: is.
template<class charT, class traits, size_t N> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x);
Returns:
os << x.template to_string<charT, traits, allocator<charT>>(
  use_facet<ctype<charT>>(os.getloc()).widen('0'),
  use_facet<ctype<charT>>(os.getloc()).widen('1'))
(see [ostream.formatted]).

20.10 Memory [memory]

20.10.1 In general [memory.general]

Subclause [memory] describes the contents of the header <memory> ([memory.syn]) and some of the contents of the header <cstdlib> ([cstdlib.syn]).

20.10.2 Header <memory> synopsis [memory.syn]

The header <memory> defines several types and function templates that describe properties of pointers and pointer-like types, manage memory for containers and other template types, destroy objects, and construct objects in uninitialized memory buffers ([pointer.traits][specialized.addressof] and [specialized.algorithms]).
The header also defines the templates unique_­ptr, shared_­ptr, weak_­ptr, and various function templates that operate on objects of these types ([smartptr]).
#include <compare>              // see [compare.syn]

namespace std {
  // [pointer.traits], pointer traits
  template<class Ptr> struct pointer_traits;
  template<class T> struct pointer_traits<T*>;

  // [pointer.conversion], pointer conversion
  template<class T>
    constexpr T* to_address(T* p) noexcept;
  template<class Ptr>
    constexpr auto to_address(const Ptr& p) noexcept;

  // [util.dynamic.safety], pointer safety
\indexlibraryglobal{in_place}%
\indexlibrarymember{relaxed}{pointer_safety}%
\indexlibrarymember{preferred}{pointer_safety}%
\indexlibrarymember{strict}{pointer_safety}
  enum class pointer_safety { relaxed, preferred, strict };
  void declare_reachable(void* p);
  template<class T>
    T* undeclare_reachable(T* p);
  void declare_no_pointers(char* p, size_t n);
  void undeclare_no_pointers(char* p, size_t n);
  pointer_safety get_pointer_safety() noexcept;

  // [ptr.align], pointer alignment
  void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
  template<size_t N, class T>
    [[nodiscard]] constexpr T* assume_aligned(T* ptr);

  // [allocator.tag], allocator argument tag
  struct allocator_arg_t { explicit allocator_arg_t() = default; };
  inline constexpr allocator_arg_t allocator_arg{};

  // [allocator.uses], uses_­allocator
  template<class T, class Alloc> struct uses_allocator;

  // [allocator.uses.trait], uses_­allocator
  template<class T, class Alloc>
    inline constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value;

  // [allocator.uses.construction], uses-allocator construction
  template<class T, class Alloc, class... Args>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,
                                                    Args&&... args) noexcept -> see below;
  template<class T, class Alloc, class Tuple1, class Tuple2>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t,
                                                    Tuple1&& x, Tuple2&& y)
                                                    noexcept ->  see below;
  template<class T, class Alloc>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept -> see below;
  template<class T, class Alloc, class U, class V>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,
                                                    U&& u, V&& v) noexcept -> see below;
  template<class T, class Alloc, class U, class V>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,
                                                    const pair<U,V>& pr) noexcept -> see below;
  template<class T, class Alloc, class U, class V>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,
                                                    pair<U,V>&& pr) noexcept -> see below;
  template<class T, class Alloc, class... Args>
    constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args);
  template<class T, class Alloc, class... Args>
    constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc,
                                                         Args&&... args);

  // [allocator.traits], allocator traits
  template<class Alloc> struct allocator_traits;

  // [default.allocator], the default allocator
  template<class T> class allocator;
  template<class T, class U>
    constexpr bool operator==(const allocator<T>&, const allocator<U>&) noexcept;

  // [specialized.addressof], addressof
  template<class T>
    constexpr T* addressof(T& r) noexcept;
  template<class T>
    const T* addressof(const T&&) = delete;

  // [specialized.algorithms], specialized algorithms
  // [special.mem.concepts], special memory concepts
  template<class I>
    concept no-throw-input-iterator = see below;    // exposition only
  template<class I>
    concept no-throw-forward-iterator = see below;  // exposition only
  template<class S, class I>
    concept no-throw-sentinel = see below;          // exposition only
  template<class R>
    concept no-throw-input-range = see below;       // exposition only
  template<class R>
    concept no-throw-forward-range = see below;     // exposition only

  template<class NoThrowForwardIterator>
    void uninitialized_default_construct(NoThrowForwardIterator first,
                                         NoThrowForwardIterator last);
  template<class ExecutionPolicy, class NoThrowForwardIterator>
    void uninitialized_default_construct(ExecutionPolicy&& exec,        // see [algorithms.parallel.overloads]
                                         NoThrowForwardIterator first,
                                         NoThrowForwardIterator last);
  template<class NoThrowForwardIterator, class Size>
    NoThrowForwardIterator
      uninitialized_default_construct_n(NoThrowForwardIterator first, Size n);
  template<class ExecutionPolicy, class NoThrowForwardIterator, class Size>
    NoThrowForwardIterator
      uninitialized_default_construct_n(ExecutionPolicy&& exec,         // see [algorithms.parallel.overloads]
                                        NoThrowForwardIterator first, Size n);

  namespace ranges {
    template<no-throw-forward-iterator I, no-throw-sentinel<I> S>
      requires default_initializable<iter_value_t<I>>
        I uninitialized_default_construct(I first, S last);
    template<no-throw-forward-range R>
      requires default_initializable<range_value_t<R>>
        borrowed_iterator_t<R> uninitialized_default_construct(R&& r);

    template<no-throw-forward-iterator I>
      requires default_initializable<iter_value_t<I>>
        I uninitialized_default_construct_n(I first, iter_difference_t<I> n);
  }

  template<class NoThrowForwardIterator>
    void uninitialized_value_construct(NoThrowForwardIterator first,
                                       NoThrowForwardIterator last);
  template<class ExecutionPolicy, class NoThrowForwardIterator>
    void uninitialized_value_construct(ExecutionPolicy&& exec,  // see [algorithms.parallel.overloads]
                                       NoThrowForwardIterator first,
                                       NoThrowForwardIterator last);
  template<class NoThrowForwardIterator, class Size>
    NoThrowForwardIterator
      uninitialized_value_construct_n(NoThrowForwardIterator first, Size n);
  template<class ExecutionPolicy, class NoThrowForwardIterator, class Size>
    NoThrowForwardIterator
      uninitialized_value_construct_n(ExecutionPolicy&& exec,   // see [algorithms.parallel.overloads]
                                      NoThrowForwardIterator first, Size n);

  namespace ranges {
    template<no-throw-forward-iterator I, no-throw-sentinel<I> S>
      requires default_initializable<iter_value_t<I>>
        I uninitialized_value_construct(I first, S last);
    template<no-throw-forward-range R>
      requires default_initializable<range_value_t<R>>
        borrowed_iterator_t<R> uninitialized_value_construct(R&& r);

    template<no-throw-forward-iterator I>
      requires default_initializable<iter_value_t<I>>
        I uninitialized_value_construct_n(I first, iter_difference_t<I> n);
  }

  template<class InputIterator, class NoThrowForwardIterator>
    NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last,
                                              NoThrowForwardIterator result);
  template<class ExecutionPolicy, class InputIterator, class NoThrowForwardIterator>
    NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec,   // see [algorithms.parallel.overloads]
                                              InputIterator first, InputIterator last,
                                              NoThrowForwardIterator result);
  template<class InputIterator, class Size, class NoThrowForwardIterator>
    NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n,
                                                NoThrowForwardIterator result);
  template<class ExecutionPolicy, class InputIterator, class Size, class NoThrowForwardIterator>
    NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads]
                                                InputIterator first, Size n,
                                                NoThrowForwardIterator result);

  namespace ranges {
    template<class I, class O>
      using uninitialized_copy_result = in_out_result<I, O>;
    template<input_iterator I, sentinel_for<I> S1,
             no-throw-forward-iterator O, no-throw-sentinel<O> S2>
      requires constructible_from<iter_value_t<O>, iter_reference_t<I>>
        uninitialized_copy_result<I, O>
          uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast);
    template<input_range IR, no-throw-forward-range OR>
      requires constructible_from<range_value_t<OR>, range_reference_t<IR>>
        uninitialized_copy_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>>
          uninitialized_copy(IR&& in_range, OR&& out_range);

    template<class I, class O>
      using uninitialized_copy_n_result = in_out_result<I, O>;
    template<input_iterator I, no-throw-forward-iterator O, no-throw-sentinel<O> S>
      requires constructible_from<iter_value_t<O>, iter_reference_t<I>>
        uninitialized_copy_n_result<I, O>
          uninitialized_copy_n(I ifirst, iter_difference_t<I> n, O ofirst, S olast);
  }

  template<class InputIterator, class NoThrowForwardIterator>
    NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last,
                                              NoThrowForwardIterator result);
  template<class ExecutionPolicy, class InputIterator, class NoThrowForwardIterator>
    NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec,   // see [algorithms.parallel.overloads]
                                              InputIterator first, InputIterator last,
                                              NoThrowForwardIterator result);
  template<class InputIterator, class Size, class NoThrowForwardIterator>
    pair<InputIterator, NoThrowForwardIterator>
      uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result);
  template<class ExecutionPolicy, class InputIterator, class Size, class NoThrowForwardIterator>
    pair<InputIterator, NoThrowForwardIterator>
      uninitialized_move_n(ExecutionPolicy&& exec,              // see [algorithms.parallel.overloads]
                           InputIterator first, Size n, NoThrowForwardIterator result);

  namespace ranges {
    template<class I, class O>
      using uninitialized_move_result = in_out_result<I, O>;
    template<input_iterator I, sentinel_for<I> S1,
             no-throw-forward-iterator O, no-throw-sentinel<O> S2>
      requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>>
        uninitialized_move_result<I, O>
          uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast);
    template<input_range IR, no-throw-forward-range OR>
      requires constructible_from<range_value_t<OR>, range_rvalue_reference_t<IR>>
        uninitialized_move_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>>
          uninitialized_move(IR&& in_range, OR&& out_range);

    template<class I, class O>
      using uninitialized_move_n_result = in_out_result<I, O>;
    template<input_iterator I,
             no-throw-forward-iterator O, no-throw-sentinel<O> S>
      requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>>
        uninitialized_move_n_result<I, O>
          uninitialized_move_n(I ifirst, iter_difference_t<I> n, O ofirst, S olast);
  }

  template<class NoThrowForwardIterator, class T>
    void uninitialized_fill(NoThrowForwardIterator first, NoThrowForwardIterator last,
                            const T& x);
  template<class ExecutionPolicy, class NoThrowForwardIterator, class T>
    void uninitialized_fill(ExecutionPolicy&& exec,             // see [algorithms.parallel.overloads]
                            NoThrowForwardIterator first, NoThrowForwardIterator last,
                            const T& x);
  template<class NoThrowForwardIterator, class Size, class T>
    NoThrowForwardIterator
      uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x);
  template<class ExecutionPolicy, class NoThrowForwardIterator, class Size, class T>
    NoThrowForwardIterator
      uninitialized_fill_n(ExecutionPolicy&& exec,              // see [algorithms.parallel.overloads]
                           NoThrowForwardIterator first, Size n, const T& x);

  namespace ranges {
    template<no-throw-forward-iterator I, no-throw-sentinel<I> S, class T>
      requires constructible_from<iter_value_t<I>, const T&>
        I uninitialized_fill(I first, S last, const T& x);
    template<no-throw-forward-range R, class T>
      requires constructible_from<range_value_t<R>, const T&>
        borrowed_iterator_t<R> uninitialized_fill(R&& r, const T& x);

    template<no-throw-forward-iterator I, class T>
      requires constructible_from<iter_value_t<I>, const T&>
        I uninitialized_fill_n(I first, iter_difference_t<I> n, const T& x);
  }

  // [specialized.construct], construct_­at
  template<class T, class... Args>
    constexpr T* construct_at(T* location, Args&&... args);

  namespace ranges {
    template<class T, class... Args>
      constexpr T* construct_at(T* location, Args&&... args);
  }

  // [specialized.destroy], destroy
  template<class T>
    constexpr void destroy_at(T* location);
  template<class NoThrowForwardIterator>
    constexpr void destroy(NoThrowForwardIterator first, NoThrowForwardIterator last);
  template<class ExecutionPolicy, class NoThrowForwardIterator>
    void destroy(ExecutionPolicy&& exec,                        // see [algorithms.parallel.overloads]
                 NoThrowForwardIterator first, NoThrowForwardIterator last);
  template<class NoThrowForwardIterator, class Size>
    constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, Size n);
  template<class ExecutionPolicy, class NoThrowForwardIterator, class Size>
    NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec,    // see [algorithms.parallel.overloads]
                                     NoThrowForwardIterator first, Size n);

  namespace ranges {
    template<destructible T>
      constexpr void destroy_at(T* location) noexcept;

    template<no-throw-input-iterator I, no-throw-sentinel<I> S>
      requires destructible<iter_value_t<I>>
        constexpr I destroy(I first, S last) noexcept;
    template<no-throw-input-range R>
      requires destructible<range_value_t<R>>
        constexpr borrowed_iterator_t<R> destroy(R&& r) noexcept;

    template<no-throw-input-iterator I>
      requires destructible<iter_value_t<I>>
        constexpr I destroy_n(I first, iter_difference_t<I> n) noexcept;
  }

  // [unique.ptr], class template unique_­ptr
  template<class T> struct default_delete;
  template<class T> struct default_delete<T[]>;
  template<class T, class D = default_delete<T>> class unique_ptr;
  template<class T, class D> class unique_ptr<T[], D>;

  template<class T, class... Args>
    unique_ptr<T> make_unique(Args&&... args);                                  // T is not array
  template<class T>
    unique_ptr<T> make_unique(size_t n);                                        // T is U[]
  template<class T, class... Args>
    unspecified make_unique(Args&&...) = delete;                                // T is U[N]

  template<class T>
    unique_ptr<T> make_unique_for_overwrite();                                  // T is not array
  template<class T>
    unique_ptr<T> make_unique_for_overwrite(size_t n);                          // T is U[]
  template<class T, class... Args>
    unspecified make_unique_for_overwrite(Args&&...) = delete;                  // T is U[N]

  template<class T, class D>
    void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;

  template<class T1, class D1, class T2, class D2>
    bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    requires three_way_comparable_with<typename unique_ptr<T1, D1>::pointer,
                                       typename unique_ptr<T2, D2>::pointer>
    compare_three_way_result_t<typename unique_ptr<T1, D1>::pointer,
                               typename unique_ptr<T2, D2>::pointer>
      operator<=>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

  template<class T, class D>
    bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
  template<class T, class D>
    bool operator<(const unique_ptr<T, D>& x, nullptr_t);
  template<class T, class D>
    bool operator<(nullptr_t, const unique_ptr<T, D>& y);
  template<class T, class D>
    bool operator>(const unique_ptr<T, D>& x, nullptr_t);
  template<class T, class D>
    bool operator>(nullptr_t, const unique_ptr<T, D>& y);
  template<class T, class D>
    bool operator<=(const unique_ptr<T, D>& x, nullptr_t);
  template<class T, class D>
    bool operator<=(nullptr_t, const unique_ptr<T, D>& y);
  template<class T, class D>
    bool operator>=(const unique_ptr<T, D>& x, nullptr_t);
  template<class T, class D>
    bool operator>=(nullptr_t, const unique_ptr<T, D>& y);
  template<class T, class D>
    requires three_way_comparable_with<typename unique_ptr<T, D>::pointer, nullptr_t>
    compare_three_way_result_t<typename unique_ptr<T, D>::pointer, nullptr_t>
      operator<=>(const unique_ptr<T, D>& x, nullptr_t);

  template<class E, class T, class Y, class D>
    basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const unique_ptr<Y, D>& p);

  // [util.smartptr.weak.bad], class bad_­weak_­ptr
  class bad_weak_ptr;

  // [util.smartptr.shared], class template shared_­ptr
  template<class T> class shared_ptr;

  // [util.smartptr.shared.create], shared_­ptr creation
  template<class T, class... Args>
    shared_ptr<T> make_shared(Args&&... args);                                  // T is not array
  template<class T, class A, class... Args>
    shared_ptr<T> allocate_shared(const A& a, Args&&... args);                  // T is not array

  template<class T>
    shared_ptr<T> make_shared(size_t N);                                        // T is U[]
  template<class T, class A>
    shared_ptr<T> allocate_shared(const A& a, size_t N);                        // T is U[]

  template<class T>
    shared_ptr<T> make_shared();                                                // T is U[N]
  template<class T, class A>
    shared_ptr<T> allocate_shared(const A& a);                                  // T is U[N]

  template<class T>
    shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u);           // T is U[]
  template<class T, class A>
    shared_ptr<T> allocate_shared(const A& a, size_t N,
                                  const remove_extent_t<T>& u);                 // T is U[]

  template<class T>
    shared_ptr<T> make_shared(const remove_extent_t<T>& u);                     // T is U[N]
  template<class T, class A>
    shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& u);     // T is U[N]

  template<class T>
    shared_ptr<T> make_shared_for_overwrite();                                  // T is not U[]
  template<class T, class A>
    shared_ptr<T> allocate_shared_for_overwrite(const A& a);                    // T is not U[]

  template<class T>
    shared_ptr<T> make_shared_for_overwrite(size_t N);                          // T is U[]
  template<class T, class A>
    shared_ptr<T> allocate_shared_for_overwrite(const A& a, size_t N);          // T is U[]

  // [util.smartptr.shared.cmp], shared_­ptr comparisons
  template<class T, class U>
    bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    strong_ordering operator<=>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;

  template<class T>
    bool operator==(const shared_ptr<T>& x, nullptr_t) noexcept;
  template<class T>
    strong_ordering operator<=>(const shared_ptr<T>& x, nullptr_t) noexcept;

  // [util.smartptr.shared.spec], shared_­ptr specialized algorithms
  template<class T>
    void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;

  // [util.smartptr.shared.cast], shared_­ptr casts
  template<class T, class U>
    shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
    shared_ptr<T> static_pointer_cast(shared_ptr<U>&& r) noexcept;
  template<class T, class U>
    shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U>&& r) noexcept;
  template<class T, class U>
    shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
    shared_ptr<T> const_pointer_cast(shared_ptr<U>&& r) noexcept;
  template<class T, class U>
    shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
    shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U>&& r) noexcept;

  // [util.smartptr.getdeleter], shared_­ptr get_­deleter
  template<class D, class T>
    D* get_deleter(const shared_ptr<T>& p) noexcept;

  // [util.smartptr.shared.io], shared_­ptr I/O
  template<class E, class T, class Y>
    basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const shared_ptr<Y>& p);

  // [util.smartptr.weak], class template weak_­ptr
  template<class T> class weak_ptr;

  // [util.smartptr.weak.spec], weak_­ptr specialized algorithms
  template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;

  // [util.smartptr.ownerless], class template owner_­less
  template<class T = void> struct owner_less;

  // [util.smartptr.enab], class template enable_­shared_­from_­this
  template<class T> class enable_shared_from_this;

  // [util.smartptr.hash], hash support
  template<class T> struct hash;
  template<class T, class D> struct hash<unique_ptr<T, D>>;
  template<class T> struct hash<shared_ptr<T>>;

  // [util.smartptr.atomic], atomic smart pointers
  template<class T> struct atomic;
  template<class T> struct atomic<shared_ptr<T>>;
  template<class T> struct atomic<weak_ptr<T>>;
}

20.10.3 Pointer traits [pointer.traits]

The class template pointer_­traits supplies a uniform interface to certain attributes of pointer-like types.
namespace std {
  template<class Ptr> struct pointer_traits {
    using pointer         = Ptr;
    using element_type    = see below;
    using difference_type = see below;

    template<class U> using rebind = see below;

    static pointer pointer_to(see below r);
  };

  template<class T> struct pointer_traits<T*> {
    using pointer         = T*;
    using element_type    = T;
    using difference_type = ptrdiff_t;

    template<class U> using rebind = U*;

    static constexpr pointer pointer_to(see below r) noexcept;
  };
}

20.10.3.1 Member types [pointer.traits.types]

using element_type = see below;
Type: Ptr​::​element_­type if the qualified-id Ptr​::​element_­type is valid and denotes a type ([temp.deduct]); otherwise, T if Ptr is a class template instantiation of the form SomePointer<T, Args>, where Args is zero or more type arguments; otherwise, the specialization is ill-formed.
using difference_type = see below;
Type: Ptr​::​difference_­type if the qualified-id Ptr​::​difference_­type is valid and denotes a type ([temp.deduct]); otherwise, ptrdiff_­t.
template<class U> using rebind = see below;
Alias template: Ptr​::​rebind<U> if the qualified-id Ptr​::​rebind<U> is valid and denotes a type ([temp.deduct]); otherwise, SomePointer<U, Args> if Ptr is a class template instantiation of the form SomePointer<T, Args>, where Args is zero or more type arguments; otherwise, the instantiation of rebind is ill-formed.

20.10.3.2 Member functions [pointer.traits.functions]

static pointer pointer_traits::pointer_to(see below r); static constexpr pointer pointer_traits<T*>::pointer_to(see below r) noexcept;
Mandates: For the first member function, Ptr​::​pointer_­to(r) is well-formed.
Preconditions: For the first member function, Ptr​::​pointer_­to(r) returns a pointer to r through which indirection is valid.
Returns: The first member function returns Ptr​::​pointer_­to(r).
The second member function returns addressof(r).
Remarks: If element_­type is cv void, the type of r is unspecified; otherwise, it is element_­type&.

20.10.3.3 Optional members [pointer.traits.optmem]

Specializations of pointer_­traits may define the member declared in this subclause to customize the behavior of the standard library.
static element_type* to_address(pointer p) noexcept;
Returns: A pointer of type element_­type* that references the same location as the argument p.
Note
:
This function should be the inverse of pointer_­to.
If defined, it customizes the behavior of the non-member function to_­address ([pointer.conversion]).
— end note
 ]

20.10.4 Pointer conversion [pointer.conversion]

template<class T> constexpr T* to_address(T* p) noexcept;
Mandates: T is not a function type.
Returns: p.
template<class Ptr> constexpr auto to_address(const Ptr& p) noexcept;
Returns: pointer_­traits<Ptr>​::​to_­address(p) if that expression is well-formed (see [pointer.traits.optmem]), otherwise to_­address(p.operator->()).

20.10.5 Pointer safety [util.dynamic.safety]

A complete object is declared reachable while the number of calls to declare_­reachable with an argument referencing the object exceeds the number of calls to undeclare_­reachable with an argument referencing the object.
void declare_reachable(void* p);
Preconditions: p is a safely-derived pointer ([basic.stc.dynamic.safety]) or a null pointer value.
Effects: If p is not null, the complete object referenced by p is subsequently declared reachable ([basic.stc.dynamic.safety]).
Throws: May throw bad_­alloc if the system cannot allocate additional memory that may be required to track objects declared reachable.
template<class T> T* undeclare_reachable(T* p);
Preconditions: If p is not null, the complete object referenced by p has been previously declared reachable, and is live ([basic.life]) from the time of the call until the last undeclare_­reachable(p) call on the object.
Returns: A safely derived copy of p which compares equal to p.
Throws: Nothing.
Note
:
It is expected that calls to declare_­reachable(p) will consume a small amount of memory in addition to that occupied by the referenced object until the matching call to undeclare_­reachable(p) is encountered.
Long running programs should arrange that calls are matched.
— end note
 ]
void declare_no_pointers(char* p, size_t n);
Preconditions: No bytes in the specified range are currently registered with declare_­no_­pointers().
If the specified range is in an allocated object, then it is entirely within a single allocated object.
The object is live until the corresponding undeclare_­no_­pointers() call.
Note
:
In a garbage-collecting implementation, the fact that a region in an object is registered with declare_­no_­pointers() should not prevent the object from being collected.
— end note
 ]
Effects: The n bytes starting at p no longer contain traceable pointer locations, independent of their type.
Hence indirection through a pointer located there is undefined if the object it points to was created by global operator new and not previously declared reachable.
Note
:
This may be used to inform a garbage collector or leak detector that this region of memory need not be traced.
— end note
 ]
Throws: Nothing.
Note
:
Under some conditions implementations may need to allocate memory.
However, the request can be ignored if memory allocation fails.
— end note
 ]
void undeclare_no_pointers(char* p, size_t n);
Preconditions: The same range has previously been passed to declare_­no_­pointers().
Effects: Unregisters a range registered with declare_­no_­pointers() for destruction.
It shall be called before the lifetime of the object ends.
Throws: Nothing.
pointer_safety get_pointer_safety() noexcept;
Returns: pointer_­safety​::​strict if the implementation has strict pointer safety.
It is implementation-defined whether get_­pointer_­safety returns pointer_­safety​::​relaxed or pointer_­safety​::​preferred if the implementation has relaxed pointer safety.219
pointer_­safety​::​preferred might be returned to indicate that a leak detector is running so that the program can avoid spurious leak reports.

20.10.6 Pointer alignment [ptr.align]

void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
Preconditions:
  • alignment is a power of two
  • ptr represents the address of contiguous storage of at least space bytes
Effects: If it is possible to fit size bytes of storage aligned by alignment into the buffer pointed to by ptr with length space, the function updates ptr to represent the first possible address of such storage and decreases space by the number of bytes used for alignment.
Otherwise, the function does nothing.
Returns: A null pointer if the requested aligned buffer would not fit into the available space, otherwise the adjusted value of ptr.
Note
:
The function updates its ptr and space arguments so that it can be called repeatedly with possibly different alignment and size arguments for the same buffer.
— end note
 ]
template<size_t N, class T> [[nodiscard]] constexpr T* assume_aligned(T* ptr);
Mandates: N is a power of two.
Preconditions: ptr points to an object X of a type similar ([conv.qual]) to T, where X has alignment N ([basic.align]).
Returns: ptr.
Throws: Nothing.
Note
:
The alignment assumption on an object X expressed by a call to assume_­aligned may result in generation of more efficient code.
It is up to the program to ensure that the assumption actually holds.
The call does not cause the compiler to verify or enforce this.
An implementation might only make the assumption for those operations on X that access X through the pointer returned by assume_­aligned.
— end note
 ]

20.10.7 Allocator argument tag [allocator.tag]

namespace std { struct allocator_arg_t { explicit allocator_arg_t() = default; }; inline constexpr allocator_arg_t allocator_arg{}; }
The allocator_­arg_­t struct is an empty class type used as a unique type to disambiguate constructor and function overloading.
Specifically, several types (see tuple [tuple]) have constructors with allocator_­arg_­t as the first argument, immediately followed by an argument of a type that meets the Cpp17Allocator requirements (Table 36).

20.10.8 uses_­allocator [allocator.uses]

20.10.8.1 uses_­allocator trait [allocator.uses.trait]

template<class T, class Alloc> struct uses_allocator;
Remarks: Automatically detects whether T has a nested allocator_­type that is convertible from Alloc.
Meets the Cpp17BinaryTypeTrait requirements ([meta.rqmts]).
The implementation shall provide a definition that is derived from true_­type if the qualified-id T​::​allocator_­type is valid and denotes a type ([temp.deduct]) and is_­convertible_­v<Alloc, T​::​allocator_­type> != false, otherwise it shall be derived from false_­type.
A program may specialize this template to derive from true_­type for a program-defined type T that does not have a nested allocator_­type but nonetheless can be constructed with an allocator where either:
  • the first argument of a constructor has type allocator_­arg_­t and the second argument has type Alloc or
  • the last argument of a constructor has type Alloc.

20.10.8.2 Uses-allocator construction [allocator.uses.construction]

Uses-allocator construction with allocator alloc and constructor arguments args... refers to the construction of an object of type T such that alloc is passed to the constructor of T if T uses an allocator type compatible with alloc.
When applied to the construction of an object of type T, it is equivalent to initializing it with the value of the expression make_­obj_­using_­allocator<T>(alloc, args...), described below.
The following utility functions support three conventions for passing alloc to a constructor:
  • If T does not use an allocator compatible with alloc, then alloc is ignored.
  • Otherwise, if T has a constructor invocable as T(allocator_­arg, alloc, args...) (leading-allocator convention), then uses-allocator construction chooses this constructor form.
  • Otherwise, if T has a constructor invocable as T(args..., alloc) (trailing-allocator convention), then uses-allocator construction chooses this constructor form.
The uses_­allocator_­construction_­args function template takes an allocator and argument list and produces (as a tuple) a new argument list matching one of the above conventions.
Additionally, overloads are provided that treat specializations of pair such that uses-allocator construction is applied individually to the first and second data members.
The make_­obj_­using_­allocator and uninitialized_­construct_­using_­allocator function templates apply the modified constructor arguments to construct an object of type T as a return value or in-place, respectively.
Note
:
For uses_­allocator_­construction_­args and make_­obj_­using_­allocator, type T is not deduced and must therefore be specified explicitly by the caller.
— end note
 ]
template<class T, class Alloc, class... Args> constexpr auto uses_allocator_construction_args(const Alloc& alloc, Args&&... args) noexcept -> see below;
Constraints: T is not a specialization of pair.
Returns: A tuple value determined as follows:
  • If uses_­allocator_­v<T, Alloc> is false and is_­constructible_­v<T, Args...> is true, return forward_­as_­tuple(std​::​forward<Args>(args)...).
  • Otherwise, if uses_­allocator_­v<T, Alloc> is true and is_­constructible_­v<T, allocator_­arg_­t, const Alloc&, Args...> is true, return
    tuple<allocator_arg_t, const Alloc&, Args&&...>(
      allocator_arg, alloc, std::forward<Args>(args)...)
    
  • Otherwise, if uses_­allocator_­v<T, Alloc> is true and is_­constructible_­v<T, Args..., const Alloc&> is true, return forward_­as_­tuple(std​::​forward<Args>(args)..., alloc).
  • Otherwise, the program is ill-formed.
Note
:
This definition prevents a silent failure to pass the allocator to a constructor of a type for which uses_­allocator_­v<T, Alloc> is true.
— end note
 ]
template<class T, class Alloc, class Tuple1, class Tuple2> constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, Tuple1&& x, Tuple2&& y) noexcept -> see below;
Constraints: T is a specialization of pair.
Effects: For T specified as pair<T1, T2>, equivalent to:
return make_tuple(
  piecewise_construct,
  apply([&alloc](auto&&... args1) {
          return uses_allocator_construction_args<T1>(
            alloc, std::forward<decltype(args1)>(args1)...);
        }, std::forward<Tuple1>(x)),
  apply([&alloc](auto&&... args2) {
          return uses_allocator_construction_args<T2>(
            alloc, std::forward<decltype(args2)>(args2)...);
        }, std::forward<Tuple2>(y)));
template<class T, class Alloc> constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept -> see below;
Constraints: T is a specialization of pair.
Effects: Equivalent to:
return uses_allocator_construction_args<T>(alloc, piecewise_construct,
                                           tuple<>{}, tuple<>{});
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u, V&& v) noexcept -> see below;
Constraints: T is a specialization of pair.
Effects: Equivalent to:
return uses_allocator_construction_args<T>(alloc, piecewise_construct,
                                           forward_as_tuple(std::forward<U>(u)),
                                           forward_as_tuple(std::forward<V>(v)));
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair<U,V>& pr) noexcept -> see below;
Constraints: T is a specialization of pair.
Effects: Equivalent to:
return uses_allocator_construction_args<T>(alloc, piecewise_construct,
                                           forward_as_tuple(pr.first),
                                           forward_as_tuple(pr.second));
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U,V>&& pr) noexcept -> see below;
Constraints: T is a specialization of pair.
Effects: Equivalent to:
return uses_allocator_construction_args<T>(alloc, piecewise_construct,
                                           forward_as_tuple(std::move(pr).first),
                                           forward_as_tuple(std::move(pr).second));
template<class T, class Alloc, class... Args> constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args);
Effects: Equivalent to:
return make_from_tuple<T>(uses_allocator_construction_args<T>(
                            alloc, std::forward<Args>(args)...));
template<class T, class Alloc, class... Args> constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args);
Effects: Equivalent to:
return apply([&]<class... U>(U&&... xs) {
       return construct_at(p, std::forward<U>(xs)...);
     }, uses_allocator_construction_args<T>(alloc, std::forward<Args>(args)...));

20.10.9 Allocator traits [allocator.traits]

The class template allocator_­traits supplies a uniform interface to all allocator types.
An allocator cannot be a non-class type, however, even if allocator_­traits supplies the entire required interface.
Note
:
Thus, it is always possible to create a derived class from an allocator.
— end note
 ]
namespace std {
  template<class Alloc> struct allocator_traits {
    using allocator_type     = Alloc;

    using value_type         = typename Alloc::value_type;

    using pointer            = see below;
    using const_pointer      = see below;
    using void_pointer       = see below;
    using const_void_pointer = see below;

    using difference_type    = see below;
    using size_type          = see below;

    using propagate_on_container_copy_assignment = see below;
    using propagate_on_container_move_assignment = see below;
    using propagate_on_container_swap            = see below;
    using is_always_equal                        = see below;

    template<class T> using rebind_alloc = see below;
    template<class T> using rebind_traits = allocator_traits<rebind_alloc<T>>;

    [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n);
    [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n,
                                                    const_void_pointer hint);

    static constexpr void deallocate(Alloc& a, pointer p, size_type n);

    template<class T, class... Args>
      static constexpr void construct(Alloc& a, T* p, Args&&... args);

    template<class T>
      static constexpr void destroy(Alloc& a, T* p);

    static constexpr size_type max_size(const Alloc& a) noexcept;

    static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs);
  };
}

20.10.9.1 Member types [allocator.traits.types]

using pointer = see below;
Type: Alloc​::​pointer if the qualified-id Alloc​::​pointer is valid and denotes a type ([temp.deduct]); otherwise, value_­type*.
using const_pointer = see below;
Type: Alloc​::​const_­pointer if the qualified-id Alloc​::​const_­pointer is valid and denotes a type ([temp.deduct]); otherwise, pointer_­traits<pointer>​::​rebind<const value_­type>.
using void_pointer = see below;
Type: Alloc​::​void_­pointer if the qualified-id Alloc​::​void_­pointer is valid and denotes a type ([temp.deduct]); otherwise, pointer_­traits<pointer>​::​rebind<void>.
using const_void_pointer = see below;
Type: Alloc​::​const_­void_­pointer if the qualified-id Alloc​::​const_­void_­pointer is valid and denotes a type ([temp.deduct]); otherwise, pointer_­traits<pointer>​::​​rebind<const void>.
using difference_type = see below;
Type: Alloc​::​difference_­type if the qualified-id Alloc​::​difference_­type is valid and denotes a type ([temp.deduct]); otherwise, pointer_­traits<pointer>​::​difference_­type.
using size_type = see below;
Type: Alloc​::​size_­type if the qualified-id Alloc​::​size_­type is valid and denotes a type ([temp.deduct]); otherwise, make_­unsigned_­t<difference_­type>.
using propagate_on_container_copy_assignment = see below;
Type: Alloc​::​propagate_­on_­container_­copy_­assignment if the qualified-id Alloc​::​propagate_­on_­container_­copy_­assignment is valid and denotes a type ([temp.deduct]); otherwise false_­type.
using propagate_on_container_move_assignment = see below;
Type: Alloc​::​propagate_­on_­container_­move_­assignment if the qualified-id Alloc​::​propagate_­on_­container_­move_­assignment is valid and denotes a type ([temp.deduct]); otherwise false_­type.
using propagate_on_container_swap = see below;
Type: Alloc​::​propagate_­on_­container_­swap if the qualified-id Alloc​::​propagate_­on_­container_­swap is valid and denotes a type ([temp.deduct]); otherwise false_­type.
using is_always_equal = see below;
Type: Alloc​::​is_­always_­equal if the qualified-id Alloc​::​is_­always_­equal is valid and denotes a type ([temp.deduct]); otherwise is_­empty<Alloc>​::​type.
template<class T> using rebind_alloc = see below;
Alias template: Alloc​::​rebind<T>​::​other if the qualified-id Alloc​::​rebind<T>​::​other is valid and denotes a type ([temp.deduct]); otherwise, Alloc<T, Args> if Alloc is a class template instantiation of the form Alloc<U, Args>, where Args is zero or more type arguments; otherwise, the instantiation of rebind_­alloc is ill-formed.

20.10.9.2 Static member functions [allocator.traits.members]

[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n);
Returns: a.allocate(n).
[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint);
Returns: a.allocate(n, hint) if that expression is well-formed; otherwise, a.allocate(n).
static constexpr void deallocate(Alloc& a, pointer p, size_type n);
Effects: Calls a.deallocate(p, n).
Throws: Nothing.
template<class T, class... Args> static constexpr void construct(Alloc& a, T* p, Args&&... args);
Effects: Calls a.construct(p, std​::​forward<Args>(args)...) if that call is well-formed; otherwise, invokes construct_­at(p, std​::​forward<Args>(args)...).
template<class T> static constexpr void destroy(Alloc& a, T* p);
Effects: Calls a.destroy(p) if that call is well-formed; otherwise, invokes destroy_­at(p).
static constexpr size_type max_size(const Alloc& a) noexcept;
Returns: a.max_­size() if that expression is well-formed; otherwise, numeric_­limits<size_­type>​::​​max()/sizeof(value_­type).
static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs);
Returns: rhs.select_­on_­container_­copy_­construction() if that expression is well-formed; otherwise, rhs.

20.10.10 The default allocator [default.allocator]

All specializations of the default allocator meet the allocator completeness requirements ([allocator.requirements.completeness]).
namespace std {
  template<class T> class allocator {
   public:
    using value_type                             = T;
    using size_type                              = size_t;
    using difference_type                        = ptrdiff_t;
    using propagate_on_container_move_assignment = true_type;
    using is_always_equal                        = true_type;

    constexpr allocator() noexcept;
    constexpr allocator(const allocator&) noexcept;
    template<class U> constexpr allocator(const allocator<U>&) noexcept;
    constexpr ~allocator();
    constexpr allocator& operator=(const allocator&) = default;

    [[nodiscard]] constexpr T* allocate(size_t n);
    constexpr void deallocate(T* p, size_t n);
  };
}

20.10.10.1 Members [allocator.members]

Except for the destructor, member functions of the default allocator shall not introduce data races as a result of concurrent calls to those member functions from different threads.
Calls to these functions that allocate or deallocate a particular unit of storage shall occur in a single total order, and each such deallocation call shall happen before the next allocation (if any) in this order.
[[nodiscard]] constexpr T* allocate(size_t n);
Mandates: T is not an incomplete type ([basic.types]).
Returns: A pointer to the initial element of an array of n T.
Remarks: The storage for the array is obtained by calling ​::​operator new, but it is unspecified when or how often this function is called.
This function starts the lifetime of the array object, but not that of any of the array elements.
Throws: bad_­array_­new_­length if numeric_­limits<size_­t>​::​max() / sizeof(T) < n, or bad_­alloc if the storage cannot be obtained.
constexpr void deallocate(T* p, size_t n);
Preconditions: p is a pointer value obtained from allocate().
n equals the value passed as the first argument to the invocation of allocate which returned p.
Effects: Deallocates the storage referenced by p .
Remarks: Uses ​::​operator delete, but it is unspecified when this function is called.

20.10.10.2 Operators [allocator.globals]

template<class T, class U> constexpr bool operator==(const allocator<T>&, const allocator<U>&) noexcept;
Returns: true.

20.10.11 addressof [specialized.addressof]

template<class T> constexpr T* addressof(T& r) noexcept;
Returns: The actual address of the object or function referenced by r, even in the presence of an overloaded operator&.
Remarks: An expression addressof(E) is a constant subexpression ([defns.const.subexpr]) if E is an lvalue constant subexpression.

20.10.12 C library memory allocation [c.malloc]

Note
:
The header <cstdlib> ([cstdlib.syn]) declares the functions described in this subclause.
— end note
 ]
void* aligned_alloc(size_t alignment, size_t size); void* calloc(size_t nmemb, size_t size); void* malloc(size_t size); void* realloc(void* ptr, size_t size);
Effects: These functions have the semantics specified in the C standard library.
Remarks: These functions do not attempt to allocate storage by calling ​::​operator new() ([new.delete]).
Storage allocated directly with these functions is implicitly declared reachable (see [basic.stc.dynamic.safety]) on allocation, ceases to be declared reachable on deallocation, and need not cease to be declared reachable as the result of an undeclare_­reachable() call.
Note
:
This allows existing C libraries to remain unaffected by restrictions on pointers that are not safely derived, at the expense of providing far fewer garbage collection and leak detection options for malloc()-allocated objects.
It also allows malloc() to be implemented with a separate allocation arena, bypassing the normal declare_­reachable() implementation.
The above functions should never intentionally be used as a replacement for declare_­reachable(), and newly written code is strongly encouraged to treat memory allocated with these functions as though it were allocated with operator new.
— end note
 ]
These functions implicitly create objects ([intro.object]) in the returned region of storage and return a pointer to a suitable created object.
In the case of calloc and realloc, the objects are created before the storage is zeroed or copied, respectively.
void free(void* ptr);
Effects: This function has the semantics specified in the C standard library.
Remarks: This function does not attempt to deallocate storage by calling ​::​operator delete().
See also: ISO C 7.22.3

20.11 Smart pointers [smartptr]

20.11.1 Class template unique_­ptr [unique.ptr]

A unique pointer is an object that owns another object and manages that other object through a pointer.
More precisely, a unique pointer is an object u that stores a pointer to a second object p and will dispose of p when u is itself destroyed (e.g., when leaving block scope ([stmt.dcl])).
In this context, u is said to own p.
The mechanism by which u disposes of p is known as p's associated deleter, a function object whose correct invocation results in p's appropriate disposition (typically its deletion).
Let the notation u.p denote the pointer stored by u, and let u.d denote the associated deleter.
Upon request, u can reset (replace) u.p and u.d with another pointer and deleter, but properly disposes of its owned object via the associated deleter before such replacement is considered completed.
Each object of a type U instantiated from the unique_­ptr template specified in this subclause has the strict ownership semantics, specified above, of a unique pointer.
In partial satisfaction of these semantics, each such U is Cpp17MoveConstructible and Cpp17MoveAssignable, but is not Cpp17CopyConstructible nor Cpp17CopyAssignable.
The template parameter T of unique_­ptr may be an incomplete type.
Note
:
The uses of unique_­ptr include providing exception safety for dynamically allocated memory, passing ownership of dynamically allocated memory to a function, and returning dynamically allocated memory from a function.
— end note
 ]

20.11.1.1 Default deleters [unique.ptr.dltr]

20.11.1.1.1 In general [unique.ptr.dltr.general]

The class template default_­delete serves as the default deleter (destruction policy) for the class template unique_­ptr.
The template parameter T of default_­delete may be an incomplete type.

20.11.1.1.2 default_­delete [unique.ptr.dltr.dflt]

namespace std {
  template<class T> struct default_delete {
    constexpr default_delete() noexcept = default;
    template<class U> default_delete(const default_delete<U>&) noexcept;
    void operator()(T*) const;
  };
}
template<class U> default_delete(const default_delete<U>& other) noexcept;
Constraints: U* is implicitly convertible to T*.
Effects: Constructs a default_­delete object from another default_­delete<U> object.
void operator()(T* ptr) const;
Mandates: T is a complete type.
Effects: Calls delete on ptr.

20.11.1.1.3 default_­delete<T[]> [unique.ptr.dltr.dflt1]

namespace std {
  template<class T> struct default_delete<T[]> {
    constexpr default_delete() noexcept = default;
    template<class U> default_delete(const default_delete<U[]>&) noexcept;
    template<class U> void operator()(U* ptr) const;
  };
}
template<class U> default_delete(const default_delete<U[]>& other) noexcept;
Constraints: U(*)[] is convertible to T(*)[].
Effects: Constructs a default_­delete object from another default_­delete<U[]> object.
template<class U> void operator()(U* ptr) const;
Mandates: U is a complete type.
Constraints: U(*)[] is convertible to T(*)[].
Effects: Calls delete[] on ptr.

20.11.1.2 unique_­ptr for single objects [unique.ptr.single]

namespace std {
  template<class T, class D = default_delete<T>> class unique_ptr {
  public:
    using pointer      = see below;
    using element_type = T;
    using deleter_type = D;

    // [unique.ptr.single.ctor], constructors
    constexpr unique_ptr() noexcept;
    explicit unique_ptr(pointer p) noexcept;
    unique_ptr(pointer p, see below d1) noexcept;
    unique_ptr(pointer p, see below d2) noexcept;
    unique_ptr(unique_ptr&& u) noexcept;
    constexpr unique_ptr(nullptr_t) noexcept;
    template<class U, class E>
      unique_ptr(unique_ptr<U, E>&& u) noexcept;

    // [unique.ptr.single.dtor], destructor
    ~unique_ptr();

    // [unique.ptr.single.asgn], assignment
    unique_ptr& operator=(unique_ptr&& u) noexcept;
    template<class U, class E>
      unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
    unique_ptr& operator=(nullptr_t) noexcept;

    // [unique.ptr.single.observers], observers
    add_lvalue_reference_t<T> operator*() const;
    pointer operator->() const noexcept;
    pointer get() const noexcept;
    deleter_type& get_deleter() noexcept;
    const deleter_type& get_deleter() const noexcept;
    explicit operator bool() const noexcept;

    // [unique.ptr.single.modifiers], modifiers
    pointer release() noexcept;
    void reset(pointer p = pointer()) noexcept;
    void swap(unique_ptr& u) noexcept;

    // disable copy from lvalue
    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;
  };
}
The default type for the template parameter D is default_­delete.
A client-supplied template argument D shall be a function object type, lvalue reference to function, or lvalue reference to function object type for which, given a value d of type D and a value ptr of type unique_­ptr<T, D>​::​pointer, the expression d(ptr) is valid and has the effect of disposing of the pointer as appropriate for that deleter.
If the deleter's type D is not a reference type, D shall meet the Cpp17Destructible requirements (Table 32).
If the qualified-id remove_­reference_­t<D>​::​pointer is valid and denotes a type ([temp.deduct]), then unique_­ptr<T, D>​::​pointer shall be a synonym for remove_­reference_­t<D>​::​pointer.
Otherwise unique_­ptr<T, D>​::​pointer shall be a synonym for element_­type*.
The type unique_­ptr<T, D>​::​pointer shall meet the Cpp17NullablePointer requirements (Table 33).
Example
:
Given an allocator type X (Table 36) and letting A be a synonym for allocator_­traits<X>, the types A​::​pointer, A​::​const_­pointer, A​::​void_­pointer, and A​::​const_­void_­pointer may be used as unique_­ptr<T, D>​::​pointer.
— end example
 ]

20.11.1.2.1 Constructors [unique.ptr.single.ctor]

constexpr unique_ptr() noexcept; constexpr unique_ptr(nullptr_t) noexcept;
Preconditions: D meets the Cpp17DefaultConstructible requirements (Table 27), and that construction does not throw an exception.
Constraints: is_­pointer_­v<deleter_­type> is false and is_­default_­constructible_­v<deleter_­type> is true.
Effects: Constructs a unique_­ptr object that owns nothing, value-initializing the stored pointer and the stored deleter.
Postconditions: get() == nullptr.
get_­deleter() returns a reference to the stored deleter.
explicit unique_ptr(pointer p) noexcept;
Constraints: is_­pointer_­v<deleter_­type> is false and is_­default_­constructible_­v<deleter_­type> is true.
Mandates: This constructor is not selected by class template argument deduction ([over.match.class.deduct]).
Preconditions: D meets the Cpp17DefaultConstructible requirements (Table 27), and that construction does not throw an exception.
Effects: Constructs a unique_­ptr which owns p, initializing the stored pointer with p and value-initializing the stored deleter.
Postconditions: get() == p.
get_­deleter() returns a reference to the stored deleter.
unique_ptr(pointer p, const D& d) noexcept; unique_ptr(pointer p, remove_reference_t<D>&& d) noexcept;
Constraints: is_­constructible_­v<D, decltype(d)> is true.
Mandates: These constructors are not selected by class template argument deduction ([over.match.class.deduct]).
Preconditions: For the first constructor, if D is not a reference type, D meets the Cpp17CopyConstructible requirements and such construction does not exit via an exception.
For the second constructor, if D is not a reference type, D meets the Cpp17MoveConstructible requirements and such construction does not exit via an exception.
Effects: Constructs a unique_­ptr object which owns p, initializing the stored pointer with p and initializing the deleter from std​::​forward<decltype(d)>(d).
Postconditions: get() == p.
get_­deleter() returns a reference to the stored deleter.
If D is a reference type then get_­deleter() returns a reference to the lvalue d.
Remarks: If D is a reference type, the second constructor is defined as deleted.
Example
:
D d;
unique_ptr<int, D> p1(new int, D());        // D must be Cpp17MoveConstructible
unique_ptr<int, D> p2(new int, d);          // D must be Cpp17CopyConstructible
unique_ptr<int, D&> p3(new int, d);         // p3 holds a reference to d
unique_ptr<int, const D&> p4(new int, D()); // error: rvalue deleter object combined
                                            // with reference deleter type
— end example
 ]
unique_ptr(unique_ptr&& u) noexcept;
Constraints: is_­move_­constructible_­v<D> is true.
Preconditions: If D is not a reference type, D meets the Cpp17MoveConstructible requirements (Table 28).
Construction of the deleter from an rvalue of type D does not throw an exception.
Effects: Constructs a unique_­ptr from u.
If D is a reference type, this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter.
Note
:
The construction of the deleter can be implemented with std​::​forward<D>.
— end note
 ]
Postconditions: get() yields the value u.get() yielded before the construction.
u.get() == nullptr.
get_­deleter() returns a reference to the stored deleter that was constructed from u.get_­deleter().
If D is a reference type then get_­deleter() and u.get_­deleter() both reference the same lvalue deleter.
template<class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept;
Constraints:
  • unique_­ptr<U, E>​::​pointer is implicitly convertible to pointer,
  • U is not an array type, and
  • either D is a reference type and E is the same type as D, or D is not a reference type and E is implicitly convertible to D.
Preconditions: If E is not a reference type, construction of the deleter from an rvalue of type E is well-formed and does not throw an exception.
Otherwise, E is a reference type and construction of the deleter from an lvalue of type E is well-formed and does not throw an exception.
Effects: Constructs a unique_­ptr from u.
If E is a reference type, this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter.
Note
:
The deleter constructor can be implemented with std​::​forward<E>.
— end note
 ]
Postconditions: get() yields the value u.get() yielded before the construction.
u.get() == nullptr.
get_­deleter() returns a reference to the stored deleter that was constructed from u.get_­deleter().

20.11.1.2.2 Destructor [unique.ptr.single.dtor]

~unique_ptr();
Preconditions: The expression get_­deleter()(get()) is well-formed, has well-defined behavior, and does not throw exceptions.
Note
:
The use of default_­delete requires T to be a complete type.
— end note
 ]
Effects: If get() == nullptr there are no effects.
Otherwise get_­deleter()(get()).

20.11.1.2.3 Assignment [unique.ptr.single.asgn]

unique_ptr& operator=(unique_ptr&& u) noexcept;
Constraints: is_­move_­assignable_­v<D> is true.
Preconditions: If D is not a reference type, D meets the Cpp17MoveAssignable requirements (Table 30) and assignment of the deleter from an rvalue of type D does not throw an exception.
Otherwise, D is a reference type; remove_­reference_­t<D> meets the Cpp17CopyAssignable requirements and assignment of the deleter from an lvalue of type D does not throw an exception.
Effects: Calls reset(u.release()) followed by get_­deleter() = std​::​forward<D>(u.get_­deleter()).
Returns: *this.
Postconditions: u.get() == nullptr.
template<class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
Constraints:
  • unique_­ptr<U, E>​::​pointer is implicitly convertible to pointer, and
  • U is not an array type, and
  • is_­assignable_­v<D&, E&&> is true.
Preconditions: If E is not a reference type, assignment of the deleter from an rvalue of type E is well-formed and does not throw an exception.
Otherwise, E is a reference type and assignment of the deleter from an lvalue of type E is well-formed and does not throw an exception.
Effects: Calls reset(u.release()) followed by get_­deleter() = std​::​forward<E>(u.get_­deleter()).
Returns: *this.
Postconditions: u.get() == nullptr.
unique_ptr& operator=(nullptr_t) noexcept;
Effects: As if by reset().
Postconditions: get() == nullptr.
Returns: *this.

20.11.1.2.4 Observers [unique.ptr.single.observers]

add_lvalue_reference_t<T> operator*() const;
Preconditions: get() != nullptr.
Returns: *get().
pointer operator->() const noexcept;
Preconditions: get() != nullptr.
Returns: get().
Note
:
The use of this function typically requires that T be a complete type.
— end note
 ]
pointer get() const noexcept;
Returns: The stored pointer.
deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept;
Returns: A reference to the stored deleter.
explicit operator bool() const noexcept;
Returns: get() != nullptr.

20.11.1.2.5 Modifiers [unique.ptr.single.modifiers]

pointer release() noexcept;
Postconditions: get() == nullptr.
Returns: The value get() had at the start of the call to release.
void reset(pointer p = pointer()) noexcept;
Preconditions: The expression get_­deleter()(get()) is well-formed, has well-defined behavior, and does not throw exceptions.
Effects: Assigns p to the stored pointer, and then if and only if the old value of the stored pointer, old_­p, was not equal to nullptr, calls get_­deleter()(old_­p).
Note
:
The order of these operations is significant because the call to get_­deleter() may destroy *this.
— end note
 ]
Postconditions: get() == p.
Note
:
The postcondition does not hold if the call to get_­deleter() destroys *this since this->get() is no longer a valid expression.
— end note
 ]
void swap(unique_ptr& u) noexcept;
Preconditions: get_­deleter() is swappable ([swappable.requirements]) and does not throw an exception under swap.
Effects: Invokes swap on the stored pointers and on the stored deleters of *this and u.

20.11.1.3 unique_­ptr for array objects with a runtime length [unique.ptr.runtime]

namespace std {
  template<class T, class D> class unique_ptr<T[], D> {
  public:
    using pointer      = see below;
    using element_type = T;
    using deleter_type = D;

    // [unique.ptr.runtime.ctor], constructors
    constexpr unique_ptr() noexcept;
    template<class U> explicit unique_ptr(U p) noexcept;
    template<class U> unique_ptr(U p, see below d) noexcept;
    template<class U> unique_ptr(U p, see below d) noexcept;
    unique_ptr(unique_ptr&& u) noexcept;
    template<class U, class E>
      unique_ptr(unique_ptr<U, E>&& u) noexcept;
    constexpr unique_ptr(nullptr_t) noexcept;

    // destructor
    ~unique_ptr();

    // assignment
    unique_ptr& operator=(unique_ptr&& u) noexcept;
    template<class U, class E>
      unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
    unique_ptr& operator=(nullptr_t) noexcept;

    // [unique.ptr.runtime.observers], observers
    T& operator[](size_t i) const;
    pointer get() const noexcept;
    deleter_type& get_deleter() noexcept;
    const deleter_type& get_deleter() const noexcept;
    explicit operator bool() const noexcept;

    // [unique.ptr.runtime.modifiers], modifiers
    pointer release() noexcept;
    template<class U> void reset(U p) noexcept;
    void reset(nullptr_t = nullptr) noexcept;
    void swap(unique_ptr& u) noexcept;

    // disable copy from lvalue
    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;
  };
}
A specialization for array types is provided with a slightly altered interface.
  • Conversions between different types of unique_­ptr<T[], D> that would be disallowed for the corresponding pointer-to-array types, and conversions to or from the non-array forms of unique_­ptr, produce an ill-formed program.
  • Pointers to types derived from T are rejected by the constructors, and by reset.
  • The observers operator* and operator-> are not provided.
  • The indexing observer operator[] is provided.
  • The default deleter will call delete[].
Descriptions are provided below only for members that differ from the primary template.
The template argument T shall be a complete type.

20.11.1.3.1 Constructors [unique.ptr.runtime.ctor]

template<class U> explicit unique_ptr(U p) noexcept;
This constructor behaves the same as the constructor in the primary template that takes a single parameter of type pointer.
Constraints:
  • U is the same type as pointer, or
  • pointer is the same type as element_­type*, U is a pointer type V*, and V(*)[] is convertible to element_­type(*)[].
template<class U> unique_ptr(U p, see below d) noexcept; template<class U> unique_ptr(U p, see below d) noexcept;
These constructors behave the same as the constructors in the primary template that take a parameter of type pointer and a second parameter.
Constraints:
  • U is the same type as pointer,
  • U is nullptr_­t, or
  • pointer is the same type as element_­type*, U is a pointer type V*, and V(*)[] is convertible to element_­type(*)[].
template<class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept;
This constructor behaves the same as in the primary template.
Constraints: Where UP is unique_­ptr<U, E>:
  • U is an array type, and
  • pointer is the same type as element_­type*, and
  • UP​::​pointer is the same type as UP​::​element_­type*, and
  • UP​::​element_­type(*)[] is convertible to element_­type(*)[], and
  • either D is a reference type and E is the same type as D, or D is not a reference type and E is implicitly convertible to D.
Note
:
This replaces the Constraints: specification of the primary template.
— end note
 ]

20.11.1.3.2 Assignment [unique.ptr.runtime.asgn]

template<class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u)noexcept;
This operator behaves the same as in the primary template.
Constraints: Where UP is unique_­ptr<U, E>:
  • U is an array type, and
  • pointer is the same type as element_­type*, and
  • UP​::​pointer is the same type as UP​::​element_­type*, and
  • UP​::​element_­type(*)[] is convertible to element_­type(*)[], and
  • is_­assignable_­v<D&, E&&> is true.
Note
:
This replaces the Constraints: specification of the primary template.
— end note
 ]

20.11.1.3.3 Observers [unique.ptr.runtime.observers]

T& operator[](size_t i) const;
Preconditions: the number of elements in the array to which the stored pointer points.
Returns: get()[i].

20.11.1.3.4 Modifiers [unique.ptr.runtime.modifiers]

void reset(nullptr_t p = nullptr) noexcept;
Effects: Equivalent to reset(pointer()).
template<class U> void reset(U p) noexcept;
This function behaves the same as the reset member of the primary template.
Constraints:
  • U is the same type as pointer, or
  • pointer is the same type as element_­type*, U is a pointer type V*, and V(*)[] is convertible to element_­type(*)[].

20.11.1.4 Creation [unique.ptr.create]

template<class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
Constraints: T is not an array type.
Returns: unique_­ptr<T>(new T(std​::​forward<Args>(args)...)).
template<class T> unique_ptr<T> make_unique(size_t n);
Constraints: T is an array of unknown bound.
Returns: unique_­ptr<T>(new remove_­extent_­t<T>[n]()).
template<class T, class... Args> unspecified make_unique(Args&&...) = delete;
Constraints: T is an array of known bound.
template<class T> unique_ptr<T> make_unique_for_overwrite();
Constraints: T is not an array type.
Returns: unique_­ptr<T>(new T).
template<class T> unique_ptr<T> make_unique_for_overwrite(size_t n);
Constraints: T is an array of unknown bound.
Returns: unique_­ptr<T>(new remove_­extent_­t<T>[n]).
template<class T, class... Args> unspecified make_unique_for_overwrite(Args&&...) = delete;
Constraints: T is an array of known bound.

20.11.1.5 Specialized algorithms [unique.ptr.special]

template<class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
Constraints: is_­swappable_­v<D> is true.
Effects: Calls x.swap(y).
template<class T1, class D1, class T2, class D2> bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: x.get() == y.get().
template<class T1, class D1, class T2, class D2> bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Let CT denote
common_type_t<typename unique_ptr<T1, D1>::pointer,
              typename unique_ptr<T2, D2>::pointer>
Mandates:
  • unique_­ptr<T1, D1>​::​pointer is implicitly convertible to CT and
  • unique_­ptr<T2, D2>​::​pointer is implicitly convertible to CT.
Preconditions: The specialization less<CT> is a function object type ([function.objects]) that induces a strict weak ordering ([alg.sorting]) on the pointer values.
Returns: less<CT>()(x.get(), y.get()).
template<class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: y < x.
template<class T1, class D1, class T2, class D2> bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: !(y < x).
template<class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: !(x < y).
template<class T1, class D1, class T2, class D2> requires three_­way_­comparable_­with<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer> compare_three_way_result_t<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer> operator<=>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: compare_­three_­way()(x.get(), y.get()).
template<class T, class D> bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
Returns: !x.
template<class T, class D> bool operator<(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> bool operator<(nullptr_t, const unique_ptr<T, D>& x);
Preconditions: The specialization less<unique_­ptr<T, D>​::​pointer> is a function object type ([function.objects]) that induces a strict weak ordering ([alg.sorting]) on the pointer values.
Returns: The first function template returns
less<unique_ptr<T, D>::pointer>()(x.get(), nullptr)
The second function template returns
less<unique_ptr<T, D>::pointer>()(nullptr, x.get())
template<class T, class D> bool operator>(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> bool operator>(nullptr_t, const unique_ptr<T, D>& x);
Returns: The first function template returns nullptr < x.
The second function template returns x < nullptr.
template<class T, class D> bool operator<=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> bool operator<=(nullptr_t, const unique_ptr<T, D>& x);
Returns: The first function template returns !(nullptr < x).
The second function template returns !(x < nullptr).
template<class T, class D> bool operator>=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> bool operator>=(nullptr_t, const unique_ptr<T, D>& x);
Returns: The first function template returns !(x < nullptr).
The second function template returns !(nullptr < x).
template<class T, class D> requires three_­way_­comparable_­with<typename unique_ptr<T, D>::pointer, nullptr_t> compare_three_way_result_t<typename unique_ptr<T, D>::pointer, nullptr_t> operator<=>(const unique_ptr<T, D>& x, nullptr_t);
Returns: compare_­three_­way()(x.get(), nullptr).

20.11.1.6 I/O [unique.ptr.io]

template<class E, class T, class Y, class D> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const unique_ptr<Y, D>& p);
Constraints: os << p.get() is a valid expression.
Effects: Equivalent to: os << p.get();
Returns: os.

20.11.2 Class bad_­weak_­ptr [util.smartptr.weak.bad]

namespace std {
  class bad_weak_ptr : public exception {
  public:
    // see [exception] for the specification of the special member functions
    const char* what() const noexcept override;
  };
}
An exception of type bad_­weak_­ptr is thrown by the shared_­ptr constructor taking a weak_­ptr.
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

20.11.3 Class template shared_­ptr [util.smartptr.shared]

The shared_­ptr class template stores a pointer, usually obtained via new.
shared_­ptr implements semantics of shared ownership; the last remaining owner of the pointer is responsible for destroying the object, or otherwise releasing the resources associated with the stored pointer.
A shared_­ptr is said to be empty if it does not own a pointer.
namespace std {
  template<class T> class shared_ptr {
  public:
    using element_type = remove_extent_t<T>;
    using weak_type    = weak_ptr<T>;

    // [util.smartptr.shared.const], constructors
    constexpr shared_ptr() noexcept;
    constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
    template<class Y>
      explicit shared_ptr(Y* p);
    template<class Y, class D>
      shared_ptr(Y* p, D d);
    template<class Y, class D, class A>
      shared_ptr(Y* p, D d, A a);
    template<class D>
      shared_ptr(nullptr_t p, D d);
    template<class D, class A>
      shared_ptr(nullptr_t p, D d, A a);
    template<class Y>
      shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;
    template<class Y>
      shared_ptr(shared_ptr<Y>&& r, element_type* p) noexcept;
    shared_ptr(const shared_ptr& r) noexcept;
    template<class Y>
      shared_ptr(const shared_ptr<Y>& r) noexcept;
    shared_ptr(shared_ptr&& r) noexcept;
    template<class Y>
      shared_ptr(shared_ptr<Y>&& r) noexcept;
    template<class Y>
      explicit shared_ptr(const weak_ptr<Y>& r);
    template<class Y, class D>
      shared_ptr(unique_ptr<Y, D>&& r);

    // [util.smartptr.shared.dest], destructor
    ~shared_ptr();

    // [util.smartptr.shared.assign], assignment
    shared_ptr& operator=(const shared_ptr& r) noexcept;
    template<class Y>
      shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    shared_ptr& operator=(shared_ptr&& r) noexcept;
    template<class Y>
      shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
    template<class Y, class D>
      shared_ptr& operator=(unique_ptr<Y, D>&& r);

    // [util.smartptr.shared.mod], modifiers
    void swap(shared_ptr& r) noexcept;
    void reset() noexcept;
    template<class Y>
      void reset(Y* p);
    template<class Y, class D>
      void reset(Y* p, D d);
    template<class Y, class D, class A>
      void reset(Y* p, D d, A a);

    // [util.smartptr.shared.obs], observers
    element_type* get() const noexcept;
    T& operator*() const noexcept;
    T* operator->() const noexcept;
    element_type& operator[](ptrdiff_t i) const;
    long use_count() const noexcept;
    explicit operator bool() const noexcept;
    template<class U>
      bool owner_before(const shared_ptr<U>& b) const noexcept;
    template<class U>
      bool owner_before(const weak_ptr<U>& b) const noexcept;
  };

  template<class T>
    shared_ptr(weak_ptr<T>) -> shared_ptr<T>;
  template<class T, class D>
    shared_ptr(unique_ptr<T, D>) -> shared_ptr<T>;
}
Specializations of shared_­ptr shall be Cpp17CopyConstructible, Cpp17CopyAssignable, and Cpp17LessThanComparable, allowing their use in standard containers.
Specializations of shared_­ptr shall be contextually convertible to bool, allowing their use in boolean expressions and declarations in conditions.
The template parameter T of shared_­ptr may be an incomplete type.
Note
:
T may be a function type.
— end note
 ]
Example
:
if (shared_ptr<X> px = dynamic_pointer_cast<X>(py)) {
  // do something with px
}
— end example
 ]
For purposes of determining the presence of a data race, member functions shall access and modify only the shared_­ptr and weak_­ptr objects themselves and not objects they refer to.
Changes in use_­count() do not reflect modifications that can introduce data races.
For the purposes of subclause [smartptr], a pointer type Y* is said to be compatible with a pointer type T* when either Y* is convertible to T* or Y is U[N] and T is cv U[].

20.11.3.1 Constructors [util.smartptr.shared.const]

In the constructor definitions below, enables shared_­from_­this with p, for a pointer p of type Y*, means that if Y has an unambiguous and accessible base class that is a specialization of enable_­shared_­from_­this, then remove_­cv_­t<Y>* shall be implicitly convertible to T* and the constructor evaluates the statement:
if (p != nullptr && p->weak_this.expired())
  p->weak_this = shared_ptr<remove_cv_t<Y>>(*this, const_cast<remove_cv_t<Y>*>(p));
The assignment to the weak_­this member is not atomic and conflicts with any potentially concurrent access to the same object ([intro.multithread]).
constexpr shared_ptr() noexcept;
Postconditions: use_­count() == 0 && get() == nullptr.
template<class Y> explicit shared_ptr(Y* p);
Mandates: Y is a complete type.
Constraints: When T is an array type, the expression delete[] p is well-formed and either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*.
When T is not an array type, the expression delete p is well-formed and Y* is convertible to T*.
Preconditions: The expression delete[] p, when T is an array type, or delete p, when T is not an array type, has well-defined behavior, and does not throw exceptions.
Effects: When T is not an array type, constructs a shared_­ptr object that owns the pointer p.
Otherwise, constructs a shared_­ptr that owns p and a deleter of an unspecified type that calls delete[] p.
When T is not an array type, enables shared_­from_­this with p.
If an exception is thrown, delete p is called when T is not an array type, delete[] p otherwise.
Postconditions: use_­count() == 1 && get() == p.
Throws: bad_­alloc, or an implementation-defined exception when a resource other than memory could not be obtained.
template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template<class D> shared_ptr(nullptr_t p, D d); template<class D, class A> shared_ptr(nullptr_t p, D d, A a);
Constraints: is_­move_­constructible_­v<D> is true, and d(p) is a well-formed expression.
For the first two overloads:
  • If T is an array type, then either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*.
  • If T is not an array type, then Y* is convertible to T*.
Preconditions: Construction of d and a deleter of type D initialized with std​::​move(d) do not throw exceptions.
The expression d(p) has well-defined behavior and does not throw exceptions.
A meets the Cpp17Allocator requirements (Table 36).
Effects: Constructs a shared_­ptr object that owns the object p and the deleter d.
When T is not an array type, the first and second constructors enable shared_­from_­this with p.
The second and fourth constructors shall use a copy of a to allocate memory for internal use.
If an exception is thrown, d(p) is called.
Postconditions: use_­count() == 1 && get() == p.
Throws: bad_­alloc, or an implementation-defined exception when a resource other than memory could not be obtained.
template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r, element_type* p) noexcept;
Effects: Constructs a shared_­ptr instance that stores p and shares ownership with the initial value of r.
Postconditions: get() == p.
For the second overload, r is empty and r.get() == nullptr.
Note
:
To avoid the possibility of a dangling pointer, the user of this constructor should ensure that p remains valid at least until the ownership group of r is destroyed.
— end note
 ]
Note
:
This constructor allows creation of an empty shared_­ptr instance with a non-null stored pointer.
— end note
 ]
shared_ptr(const shared_ptr& r) noexcept; template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
Constraints: For the second constructor, Y* is compatible with T*.
Effects: If r is empty, constructs an empty shared_­ptr object; otherwise, constructs a shared_­ptr object that shares ownership with r.
Postconditions: get() == r.get() && use_­count() == r.use_­count().
shared_ptr(shared_ptr&& r) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
Constraints: For the second constructor, Y* is compatible with T*.
Effects: Move constructs a shared_­ptr instance from r.
Postconditions: *this shall contain the old value of r.
r shall be empty.
r.get() == nullptr.
template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
Constraints: Y* is compatible with T*.
Effects: Constructs a shared_­ptr object that shares ownership with r and stores a copy of the pointer stored in r.
If an exception is thrown, the constructor has no effect.
Postconditions: use_­count() == r.use_­count().
Throws: bad_­weak_­ptr when r.expired().
template<class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
Constraints: Y* is compatible with T* and unique_­ptr<Y, D>​::​pointer is convertible to element_­type*.
Effects: If r.get() == nullptr, equivalent to shared_­ptr().
Otherwise, if D is not a reference type, equivalent to shared_­ptr(r.release(), r.get_­deleter()).
Otherwise, equivalent to shared_­ptr(r.release(), ref(r.get_­deleter())).
If an exception is thrown, the constructor has no effect.

20.11.3.2 Destructor [util.smartptr.shared.dest]

~shared_ptr();
Effects:
  • If *this is empty or shares ownership with another shared_­ptr instance (use_­count() > 1), there are no side effects.
  • Otherwise, if *this owns an object p and a deleter d, d(p) is called.
  • Otherwise, *this owns a pointer p, and delete p is called.
Note
:
Since the destruction of *this decreases the number of instances that share ownership with *this by one, after *this has been destroyed all shared_­ptr instances that shared ownership with *this will report a use_­count() that is one less than its previous value.
— end note
 ]

20.11.3.3 Assignment [util.smartptr.shared.assign]

shared_ptr& operator=(const shared_ptr& r) noexcept; template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
Effects: Equivalent to shared_­ptr(r).swap(*this).
Returns: *this.
Note
:
The use count updates caused by the temporary object construction and destruction are not observable side effects, so the implementation may meet the effects (and the implied guarantees) via different means, without creating a temporary.
In particular, in the example:
shared_ptr<int> p(new int);
shared_ptr<void> q(p);
p = p;
q = p;
both assignments may be no-ops.
— end note
 ]
shared_ptr& operator=(shared_ptr&& r) noexcept; template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
Effects: Equivalent to shared_­ptr(std​::​move(r)).swap(*this).
Returns: *this.
template<class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);
Effects: Equivalent to shared_­ptr(std​::​move(r)).swap(*this).
Returns: *this.

20.11.3.4 Modifiers [util.smartptr.shared.mod]

void swap(shared_ptr& r) noexcept;
Effects: Exchanges the contents of *this and r.
void reset() noexcept;
Effects: Equivalent to shared_­ptr().swap(*this).
template<class Y> void reset(Y* p);
Effects: Equivalent to shared_­ptr(p).swap(*this).
template<class Y, class D> void reset(Y* p, D d);
Effects: Equivalent to shared_­ptr(p, d).swap(*this).
template<class Y, class D, class A> void reset(Y* p, D d, A a);
Effects: Equivalent to shared_­ptr(p, d, a).swap(*this).

20.11.3.5 Observers [util.smartptr.shared.obs]

element_type* get() const noexcept;
Returns: The stored pointer.
T& operator*() const noexcept;
Preconditions: get() != 0.
Returns: *get().
Remarks: When T is an array type or cv void, it is unspecified whether this member function is declared.
If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well-formed.
T* operator->() const noexcept;
Preconditions: get() != 0.
Returns: get().
Remarks: When T is an array type, it is unspecified whether this member function is declared.
If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well-formed.
element_type& operator[](ptrdiff_t i) const;
Preconditions: get() != 0 && i >= 0.
If T is U[N], i < N.
Returns: get()[i].
Remarks: When T is not an array type, it is unspecified whether this member function is declared.
If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well-formed.
Throws: Nothing.
long use_count() const noexcept;
Returns: The number of shared_­ptr objects, *this included, that share ownership with *this, or 0 when *this is empty.
Synchronization: None.
Note
:
get() == nullptr does not imply a specific return value of use_­count().
— end note
 ]
Note
:
weak_­ptr<T>​::​lock() can affect the return value of use_­count().
— end note
 ]
Note
:
When multiple threads can affect the return value of use_­count(), the result should be treated as approximate.
In particular, use_­count() == 1 does not imply that accesses through a previously destroyed shared_­ptr have in any sense completed.
— end note
 ]
explicit operator bool() const noexcept;
Returns: get() != 0.
template<class U> bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept;
Returns: An unspecified value such that
  • x.owner_­before(y) defines a strict weak ordering as defined in [alg.sorting];
  • under the equivalence relation defined by owner_­before, !a.owner_­before(b) && !b.owner_­before(a), two shared_­ptr or weak_­ptr instances are equivalent if and only if they share ownership or are both empty.

20.11.3.6 Creation [util.smartptr.shared.create]

The common requirements that apply to all make_­shared, allocate_­shared, make_­shared_­for_­overwrite, and allocate_­shared_­for_­overwrite overloads, unless specified otherwise, are described below.
template<class T, ...> shared_ptr<T> make_shared(args); template<class T, class A, ...> shared_ptr<T> allocate_shared(const A& a, args); template<class T, ...> shared_ptr<T> make_shared_for_overwrite(args); template<class T, class A, ...> shared_ptr<T> allocate_shared_for_overwrite(const A& a, args);
Preconditions: A meets the Cpp17Allocator requirements (Table 36).
Effects: Allocates memory for an object of type T (or U[N] when T is U[], where N is determined from args as specified by the concrete overload).
The object is initialized from args as specified by the concrete overload.
The allocate_­shared and allocate_­shared_­for_­overwrite templates use a copy of a (rebound for an unspecified value_­type) to allocate memory.
If an exception is thrown, the functions have no effect.
Returns: A shared_­ptr instance that stores and owns the address of the newly constructed object.
Postconditions: r.get() != 0 && r.use_­count() == 1, where r is the return value.
Throws: bad_­alloc, or an exception thrown from allocate or from the initialization of the object.
Remarks:
  • Implementations should perform no more than one memory allocation.
    Note
    : This provides efficiency equivalent to an intrusive smart pointer. — end note
     ]
  • When an object of an array type U is specified to have an initial value of u (of the same type), this shall be interpreted to mean that each array element of the object has as its initial value the corresponding element from u.
  • When an object of an array type is specified to have a default initial value, this shall be interpreted to mean that each array element of the object has a default initial value.
  • When a (sub)object of a non-array type U is specified to have an initial value of v, or U(l...), where l... is a list of constructor arguments, make_­shared shall initialize this (sub)object via the expression ​::​new(pv) U(v) or ​::​new(pv) U(l...) respectively, where pv has type void* and points to storage suitable to hold an object of type U.
  • When a (sub)object of a non-array type U is specified to have an initial value of v, or U(l...), where l... is a list of constructor arguments, allocate_­shared shall initialize this (sub)object via the expression
    • allocator_­traits<A2>​::​construct(a2, pv, v) or
    • allocator_­traits<A2>​::​construct(a2, pv, l...)
    respectively, where pv points to storage suitable to hold an object of type U and a2 of type A2 is a rebound copy of the allocator a passed to allocate_­shared such that its value_­type is remove_­cv_­t<U>.
  • When a (sub)object of non-array type U is specified to have a default initial value, make_­shared shall initialize this (sub)object via the expression ​::​new(pv) U(), where pv has type void* and points to storage suitable to hold an object of type U.
  • When a (sub)object of non-array type U is specified to have a default initial value, allocate_­shared shall initialize this (sub)object via the expression allocator_­traits<A2>​::​construct(a2, pv), where pv points to storage suitable to hold an object of type U and a2 of type A2 is a rebound copy of the allocator a passed to allocate_­shared such that its value_­type is remove_­cv_­t<U>.
  • When a (sub)object of non-array type U is initialized by make_­shared_­for_­overwrite or
    allocate_­shared_­for_­overwrite, it is initialized via the expression ​::​new(pv) U, where pv has type void* and points to storage suitable to hold an object of type U.
  • Array elements are initialized in ascending order of their addresses.
  • When the lifetime of the object managed by the return value ends, or when the initialization of an array element throws an exception, the initialized elements are destroyed in the reverse order of their original construction.
  • When a (sub)object of non-array type U that was initialized by make_­shared is to be destroyed, it is destroyed via the expression pv->~U() where pv points to that object of type U.
  • When a (sub)object of non-array type U that was initialized by allocate_­shared is to be destroyed, it is destroyed via the expression allocator_­traits<A2>​::​destroy(a2, pv) where pv points to that object of type remove_­cv_­t<U> and a2 of type A2 is a rebound copy of the allocator a passed to allocate_­shared such that its value_­type is remove_­cv_­t<U>.
Note
:
These functions will typically allocate more memory than sizeof(T) to allow for internal bookkeeping structures such as reference counts.
— end note
 ]
template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); // T is not array template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args); // T is not array
Constraints: T is not an array type.
Returns: A shared_­ptr to an object of type T with an initial value T(forward<Args>(args)...).
Remarks: The shared_­ptr constructors called by these functions enable shared_­from_­this with the address of the newly constructed object of type T.
Example
:
shared_ptr<int> p = make_shared<int>(); // shared_­ptr to int()
shared_ptr<vector<int>> q = make_shared<vector<int>>(16, 1);
  // shared_­ptr to vector of 16 elements with value 1
— end example
 ]
template<class T> shared_ptr<T> make_shared(size_t N); // T is U[] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, size_t N); // T is U[]
Constraints: T is of the form U[].
Returns: A shared_­ptr to an object of type U[N] with a default initial value, where U is remove_­extent_­t<T>.
Example
:
shared_ptr<double[]> p = make_shared<double[]>(1024);
  // shared_­ptr to a value-initialized double[1024]
shared_ptr<double[][2][2]> q = make_shared<double[][2][2]>(6);
  // shared_­ptr to a value-initialized double[6][2][2]
— end example
 ]
template<class T> shared_ptr<T> make_shared(); // T is U[N] template<class T, class A> shared_ptr<T> allocate_shared(const A& a); // T is U[N]
Constraints: T is of the form U[N].
Returns: A shared_­ptr to an object of type T with a default initial value.
Example
:
shared_ptr<double[1024]> p = make_shared<double[1024]>();
  // shared_­ptr to a value-initialized double[1024]
shared_ptr<double[6][2][2]> q = make_shared<double[6][2][2]>();
  // shared_­ptr to a value-initialized double[6][2][2]
— end example
 ]
template<class T> shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // T is U[] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, size_t N, const remove_extent_t<T>& u); // T is U[]
Constraints: T is of the form U[].
Returns: A shared_­ptr to an object of type U[N], where U is remove_­extent_­t<T> and each array element has an initial value of u.
Example
:
shared_ptr<double[]> p = make_shared<double[]>(1024, 1.0);
  // shared_­ptr to a double[1024], where each element is 1.0
shared_ptr<double[][2]> q = make_shared<double[][2]>(6, {1.0, 0.0});
  // shared_­ptr to a double[6][2], where each double[2] element is {1.0, 0.0}
shared_ptr<vector<int>[]> r = make_shared<vector<int>[]>(4, {1, 2});
  // shared_­ptr to a vector<int>[4], where each vector has contents {1, 2}
— end example
 ]
template<class T> shared_ptr<T> make_shared(const remove_extent_t<T>& u); // T is U[N] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& u); // T is U[N]
Constraints: T is of the form U[N].
Returns: A shared_­ptr to an object of type T, where each array element of type remove_­extent_­t<T> has an initial value of u.
Example
:
shared_ptr<double[1024]> p = make_shared<double[1024]>(1.0);
  // shared_­ptr to a double[1024], where each element is 1.0
shared_ptr<double[6][2]> q = make_shared<double[6][2]>({1.0, 0.0});
  // shared_­ptr to a double[6][2], where each double[2] element is {1.0, 0.0}
shared_ptr<vector<int>[4]> r = make_shared<vector<int>[4]>({1, 2});
  // shared_­ptr to a vector<int>[4], where each vector has contents {1, 2}
— end example
 ]
template<class T> shared_ptr<T> make_shared_for_overwrite(); template<class T, class A> shared_ptr<T> allocate_shared_for_overwrite(const A& a);
Constraints: T is not an array of unknown bound.
Returns: A shared_­ptr to an object of type T.
Example
:
struct X { double data[1024]; };
shared_ptr<X> p = make_shared_for_overwrite<X>();
  // shared_­ptr to a default-initialized X, where each element in X​::​data has an indeterminate value

shared_ptr<double[1024]> q = make_shared_for_overwrite<double[1024]>();
  // shared_­ptr to a default-initialized double[1024], where each element has an indeterminate value
— end example
 ]
template<class T> shared_ptr<T> make_shared_for_overwrite(size_t N); template<class T, class A> shared_ptr<T> allocate_shared_for_overwrite(const A& a, size_t N);
Constraints: T is an array of unknown bound.
Returns: A shared_­ptr to an object of type U[N], where U is remove_­extent_­t<T>.
Example
:
shared_ptr<double[]> p = make_shared_for_overwrite<double[]>(1024);
  // shared_­ptr to a default-initialized double[1024], where each element has an indeterminate value
— end example
 ]

20.11.3.7 Comparison [util.smartptr.shared.cmp]

template<class T, class U> bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
Returns: a.get() == b.get().
template<class T> bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept;
Returns: !a.
template<class T, class U> strong_ordering operator<=>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
Returns: compare_­three_­way()(a.get(), b.get()).
Note
:
Defining a comparison function allows shared_­ptr objects to be used as keys in associative containers.
— end note
 ]
template<class T> strong_ordering operator<=>(const shared_ptr<T>& a, nullptr_t) noexcept;
Returns: compare_­three_­way()(a.get(), nullptr).

20.11.3.8 Specialized algorithms [util.smartptr.shared.spec]

template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
Effects: Equivalent to a.swap(b).

20.11.3.9 Casts [util.smartptr.shared.cast]

template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U>&& r) noexcept;
Mandates: The expression static_­cast<T*>((U*)nullptr) is well-formed.
Returns:
shared_ptr<T>(R, static_cast<typename shared_ptr<T>::element_type*>(r.get()))
where R is r for the first overload, and std​::​move(r) for the second.
Note
:
The seemingly equivalent expression shared_­ptr<T>(static_­cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice.
— end note
 ]
template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U>&& r) noexcept;
Mandates: The expression dynamic_­cast<T*>((U*)nullptr) is well-formed.
The expression dynamic_­cast<typename shared_­ptr<T>​::​element_­type*>(r.get()) is well formed.
Preconditions: The expression dynamic_­cast<typename shared_­ptr<T>​::​element_­type*>(r.get()) has well-defined behavior.
Returns:
  • When dynamic_­cast<typename shared_­ptr<T>​::​element_­type*>(r.get()) returns a non-null value p, shared_­ptr<T>(R, p), where R is r for the first overload, and std​::​move(r) for the second.
  • Otherwise, shared_­ptr<T>().
Note
:
The seemingly equivalent expression shared_­ptr<T>(dynamic_­cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice.
— end note
 ]
template<class T, class U> shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U>&& r) noexcept;
Mandates: The expression const_­cast<T*>((U*)nullptr) is well-formed.
Returns:
shared_ptr<T>(R, const_cast<typename shared_ptr<T>::element_type*>(r.get()))
where R is r for the first overload, and std​::​move(r) for the second.
Note
:
The seemingly equivalent expression shared_­ptr<T>(const_­cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice.
— end note
 ]
template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U>&& r) noexcept;
Mandates: The expression reinterpret_­cast<T*>((U*)nullptr) is well-formed.
Returns:
shared_ptr<T>(R, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()))
where R is r for the first overload, and std​::​move(r) for the second.
Note
:
The seemingly equivalent expression shared_­ptr<T>(reinterpret_­cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice.
— end note
 ]

20.11.3.10 get_­deleter [util.smartptr.getdeleter]

template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept;
Returns: If p owns a deleter d of type cv-unqualified D, returns addressof(d); otherwise returns nullptr.
The returned pointer remains valid as long as there exists a shared_­ptr instance that owns d.
Note
:
It is unspecified whether the pointer remains valid longer than that.
This can happen if the implementation doesn't destroy the deleter until all weak_­ptr instances that share ownership with p have been destroyed.
— end note
 ]

20.11.3.11 I/O [util.smartptr.shared.io]

template<class E, class T, class Y> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const shared_ptr<Y>& p);
Effects: As if by: os << p.get();
Returns: os.

20.11.4 Class template weak_­ptr [util.smartptr.weak]

The weak_­ptr class template stores a weak reference to an object that is already managed by a shared_­ptr.
To access the object, a weak_­ptr can be converted to a shared_­ptr using the member function lock.
namespace std {
  template<class T> class weak_ptr {
  public:
    using element_type = remove_extent_t<T>;

    // [util.smartptr.weak.const], constructors
    constexpr weak_ptr() noexcept;
    template<class Y>
      weak_ptr(const shared_ptr<Y>& r) noexcept;
    weak_ptr(const weak_ptr& r) noexcept;
    template<class Y>
      weak_ptr(const weak_ptr<Y>& r) noexcept;
    weak_ptr(weak_ptr&& r) noexcept;
    template<class Y>
      weak_ptr(weak_ptr<Y>&& r) noexcept;

    // [util.smartptr.weak.dest], destructor
    ~weak_ptr();

    // [util.smartptr.weak.assign], assignment
    weak_ptr& operator=(const weak_ptr& r) noexcept;
    template<class Y>
      weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
    template<class Y>
      weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    weak_ptr& operator=(weak_ptr&& r) noexcept;
    template<class Y>
      weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;

    // [util.smartptr.weak.mod], modifiers
    void swap(weak_ptr& r) noexcept;
    void reset() noexcept;

    // [util.smartptr.weak.obs], observers
    long use_count() const noexcept;
    bool expired() const noexcept;
    shared_ptr<T> lock() const noexcept;
    template<class U>
      bool owner_before(const shared_ptr<U>& b) const noexcept;
    template<class U>
      bool owner_before(const weak_ptr<U>& b) const noexcept;
  };

  template<class T>
    weak_ptr(shared_ptr<T>) -> weak_ptr<T>;

  // [util.smartptr.weak.spec], specialized algorithms
  template<class T>
    void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
}
Specializations of weak_­ptr shall be Cpp17CopyConstructible and Cpp17CopyAssignable, allowing their use in standard containers.
The template parameter T of weak_­ptr may be an incomplete type.

20.11.4.1 Constructors [util.smartptr.weak.const]

constexpr weak_ptr() noexcept;
Effects: Constructs an empty weak_­ptr object.
Postconditions: use_­count() == 0.
weak_ptr(const weak_ptr& r) noexcept; template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept; template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
Constraints: For the second and third constructors, Y* is compatible with T*.
Effects: If r is empty, constructs an empty weak_­ptr object; otherwise, constructs a weak_­ptr object that shares ownership with r and stores a copy of the pointer stored in r.
Postconditions: use_­count() == r.use_­count().
weak_ptr(weak_ptr&& r) noexcept; template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept;
Constraints: For the second constructor, Y* is compatible with T*.
Effects: Move constructs a weak_­ptr instance from r.
Postconditions: *this shall contain the old value of r.
r shall be empty.
r.use_­count() == 0.

20.11.4.2 Destructor [util.smartptr.weak.dest]

~weak_ptr();
Effects: Destroys this weak_­ptr object but has no effect on the object its stored pointer points to.

20.11.4.3 Assignment [util.smartptr.weak.assign]

weak_ptr& operator=(const weak_ptr& r) noexcept; template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) noexcept; template<class Y> weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
Effects: Equivalent to weak_­ptr(r).swap(*this).
Remarks: The implementation may meet the effects (and the implied guarantees) via different means, without creating a temporary object.
Returns: *this.
weak_ptr& operator=(weak_ptr&& r) noexcept; template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
Effects: Equivalent to weak_­ptr(std​::​move(r)).swap(*this).
Returns: *this.

20.11.4.4 Modifiers [util.smartptr.weak.mod]

void swap(weak_ptr& r) noexcept;
Effects: Exchanges the contents of *this and r.
void reset() noexcept;
Effects: Equivalent to weak_­ptr().swap(*this).

20.11.4.5 Observers [util.smartptr.weak.obs]

long use_count() const noexcept;
Returns: 0 if *this is empty; otherwise, the number of shared_­ptr instances that share ownership with *this.
bool expired() const noexcept;
Returns: use_­count() == 0.
shared_ptr<T> lock() const noexcept;
Returns: expired() ? shared_­ptr<T>() : shared_­ptr<T>(*this), executed atomically.
template<class U> bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept;
Returns: An unspecified value such that
  • x.owner_­before(y) defines a strict weak ordering as defined in [alg.sorting];
  • under the equivalence relation defined by owner_­before, !a.owner_­before(b) && !b.owner_­before(a), two shared_­ptr or weak_­ptr instances are equivalent if and only if they share ownership or are both empty.

20.11.4.6 Specialized algorithms [util.smartptr.weak.spec]

template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
Effects: Equivalent to a.swap(b).

20.11.5 Class template owner_­less [util.smartptr.ownerless]

The class template owner_­less allows ownership-based mixed comparisons of shared and weak pointers.
namespace std {
  template<class T = void> struct owner_less;

  template<class T> struct owner_less<shared_ptr<T>> {
    bool operator()(const shared_ptr<T>&, const shared_ptr<T>&) const noexcept;
    bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept;
    bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept;
  };

  template<class T> struct owner_less<weak_ptr<T>> {
    bool operator()(const weak_ptr<T>&, const weak_ptr<T>&) const noexcept;
    bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept;
    bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept;
  };

  template<> struct owner_less<void> {
    template<class T, class U>
      bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept;
    template<class T, class U>
      bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept;
    template<class T, class U>
      bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept;
    template<class T, class U>
      bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept;

    using is_transparent = unspecified;
  };
}
operator()(x, y) returns x.owner_­before(y).
Note
:
Note that
  • operator() defines a strict weak ordering as defined in [alg.sorting];
  • under the equivalence relation defined by operator(), !operator()(a, b) && !operator()(b, a), two shared_­ptr or weak_­ptr instances are equivalent if and only if they share ownership or are both empty.
— end note
 ]

20.11.6 Class template enable_­shared_­from_­this [util.smartptr.enab]

A class T can inherit from enable_­shared_­from_­this<T> to inherit the shared_­from_­this member functions that obtain a shared_­ptr instance pointing to *this.
Example
:
struct X: public enable_shared_from_this<X> { };

int main() {
  shared_ptr<X> p(new X);
  shared_ptr<X> q = p->shared_from_this();
  assert(p == q);
  assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership
}
— end example
 ]
namespace std {
  template<class T> class enable_shared_from_this {
  protected:
    constexpr enable_shared_from_this() noexcept;
    enable_shared_from_this(const enable_shared_from_this&) noexcept;
    enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept;
    ~enable_shared_from_this();

  public:
    shared_ptr<T> shared_from_this();
    shared_ptr<T const> shared_from_this() const;
    weak_ptr<T> weak_from_this() noexcept;
    weak_ptr<T const> weak_from_this() const noexcept;

  private:
    mutable weak_ptr<T> weak_this;  // exposition only
  };
}
The template parameter T of enable_­shared_­from_­this may be an incomplete type.
constexpr enable_shared_from_this() noexcept; enable_shared_from_this(const enable_shared_from_this<T>&) noexcept;
Effects: Value-initializes weak_­this.
enable_shared_from_this<T>& operator=(const enable_shared_from_this<T>&) noexcept;
Returns: *this.
Note
:
weak_­this is not changed.
— end note
 ]
shared_ptr<T> shared_from_this(); shared_ptr<T const> shared_from_this() const;
Returns: shared_­ptr<T>(weak_­this).
weak_ptr<T> weak_from_this() noexcept; weak_ptr<T const> weak_from_this() const noexcept;
Returns: weak_­this.

20.11.7 Smart pointer hash support [util.smartptr.hash]

template<class T, class D> struct hash<unique_ptr<T, D>>;
Letting UP be unique_­ptr<T,D>, the specialization hash<UP> is enabled ([unord.hash]) if and only if hash<typename UP​::​pointer> is enabled.
When enabled, for an object p of type UP, hash<UP>()(p) evaluates to the same value as hash<typename UP​::​pointer>()(p.get()).
The member functions are not guaranteed to be noexcept.
template<class T> struct hash<shared_ptr<T>>;
For an object p of type shared_­ptr<T>, hash<shared_­ptr<T>>()(p) evaluates to the same value as hash<typename shared_­ptr<T>​::​element_­type*>()(p.get()).

20.12 Memory resources [mem.res]

20.12.1 Header <memory_­resource> synopsis [mem.res.syn]

namespace std::pmr {
  // [mem.res.class], class memory_­resource
  class memory_resource;

  bool operator==(const memory_resource& a, const memory_resource& b) noexcept;

  // [mem.poly.allocator.class], class template polymorphic_­allocator
  template<class Tp> class polymorphic_allocator;

  template<class T1, class T2>
    bool operator==(const polymorphic_allocator<T1>& a,
                    const polymorphic_allocator<T2>& b) noexcept;

  // [mem.res.global], global memory resources
  memory_resource* new_delete_resource() noexcept;
  memory_resource* null_memory_resource() noexcept;
  memory_resource* set_default_resource(memory_resource* r) noexcept;
  memory_resource* get_default_resource() noexcept;

  // [mem.res.pool], pool resource classes
  struct pool_options;
  class synchronized_pool_resource;
  class unsynchronized_pool_resource;
  class monotonic_buffer_resource;
}

20.12.2 Class memory_­resource [mem.res.class]

The memory_­resource class is an abstract interface to an unbounded set of classes encapsulating memory resources.
namespace std::pmr {
  class memory_resource {
    static constexpr size_t max_align = alignof(max_align_t);   // exposition only

  public:
    memory_resource() = default;
    memory_resource(const memory_resource&) = default;
    virtual ~memory_resource();

    memory_resource& operator=(const memory_resource&) = default;

    [[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align);
    void deallocate(void* p, size_t bytes, size_t alignment = max_align);

    bool is_equal(const memory_resource& other) const noexcept;

  private:
    virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
    virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;

    virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
  };
}

20.12.2.1 Public member functions [mem.res.public]

~memory_resource();
Effects: Destroys this memory_­resource.
[[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align);
Effects: Equivalent to: return do_­allocate(bytes, alignment);
void deallocate(void* p, size_t bytes, size_t alignment = max_align);
Effects: Equivalent to do_­deallocate(p, bytes, alignment).
bool is_equal(const memory_resource& other) const noexcept;
Effects: Equivalent to: return do_­is_­equal(other);

20.12.2.2 Private virtual member functions [mem.res.private]

virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
Preconditions: alignment is a power of two.
Returns: A derived class shall implement this function to return a pointer to allocated storage ([basic.stc.dynamic.allocation]) with a size of at least bytes, aligned to the specified alignment.
Throws: A derived class implementation shall throw an appropriate exception if it is unable to allocate memory with the requested size and alignment.
virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;
Preconditions: p was returned from a prior call to allocate(bytes, alignment) on a memory resource equal to *this, and the storage at p has not yet been deallocated.
Effects: A derived class shall implement this function to dispose of allocated storage.
Throws: Nothing.
virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
Returns: A derived class shall implement this function to return true if memory allocated from this can be deallocated from other and vice-versa, otherwise false.
Note
:
The most-derived type of other might not match the type of this.
For a derived class D, an implementation of this function could immediately return false if dynamic_­cast<const D*>(&other) == nullptr.
— end note
 ]

20.12.2.3 Equality [mem.res.eq]

bool operator==(const memory_resource& a, const memory_resource& b) noexcept;
Returns: &a == &b || a.is_­equal(b).

20.12.3 Class template polymorphic_­allocator [mem.poly.allocator.class]

A specialization of class template pmr​::​polymorphic_­allocator meets the Cpp17Allocator requirements (Table 36).
Constructed with different memory resources, different instances of the same specialization of pmr​::​polymorphic_­allocator can exhibit entirely different allocation behavior.
This runtime polymorphism allows objects that use polymorphic_­allocator to behave as if they used different allocator types at run time even though they use the same static allocator type.
All specializations of class template pmr​::​polymorphic_­allocator meet the allocator completeness requirements ([allocator.requirements.completeness]).
namespace std::pmr {
  template<class Tp = byte> class polymorphic_allocator {
    memory_resource* memory_rsrc;       // exposition only

  public:
    using value_type = Tp;

    // [mem.poly.allocator.ctor], constructors
    polymorphic_allocator() noexcept;
    polymorphic_allocator(memory_resource* r);

    polymorphic_allocator(const polymorphic_allocator& other) = default;

    template<class U>
      polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;

    polymorphic_allocator& operator=(const polymorphic_allocator&) = delete;

    // [mem.poly.allocator.mem], member functions
    [[nodiscard]] Tp* allocate(size_t n);
    void deallocate(Tp* p, size_t n);

    [[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t));
    void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t));
    template<class T> [[nodiscard]] T* allocate_object(size_t n = 1);
    template<class T> void deallocate_object(T* p, size_t n = 1);
    template<class T, class... CtorArgs> [[nodiscard]] T* new_object(CtorArgs&&... ctor_args);
    template<class T> void delete_object(T* p);

    template<class T, class... Args>
      void construct(T* p, Args&&... args);

    template<class T>
      void destroy(T* p);

    polymorphic_allocator select_on_container_copy_construction() const;

    memory_resource* resource() const;
  };
}

20.12.3.1 Constructors [mem.poly.allocator.ctor]

polymorphic_allocator() noexcept;
Effects: Sets memory_­rsrc to get_­default_­resource().
polymorphic_allocator(memory_resource* r);
Preconditions: r is non-null.
Effects: Sets memory_­rsrc to r.
Throws: Nothing.
Note
:
This constructor provides an implicit conversion from memory_­resource*.
— end note
 ]
template<class U> polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
Effects: Sets memory_­rsrc to other.resource().

20.12.3.2 Member functions [mem.poly.allocator.mem]

[[nodiscard]] Tp* allocate(size_t n);
Effects: If numeric_­limits<size_­t>​::​max() / sizeof(Tp) < n, throws bad_­array_­new_­length.
Otherwise equivalent to:
return static_cast<Tp*>(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp)));
void deallocate(Tp* p, size_t n);
Preconditions: p was allocated from a memory resource x, equal to *memory_­rsrc, using x.allocate(n * sizeof(Tp), alignof(Tp)).
Effects: Equivalent to memory_­rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp)).
Throws: Nothing.
[[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t));
Effects: Equivalent to: return memory_­rsrc->allocate(nbytes, alignment);
Note
:
The return type is void* (rather than, e.g., byte*) to support conversion to an arbitrary pointer type U* by static_­cast<U*>, thus facilitating construction of a U object in the allocated memory.
— end note
 ]
void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t));
Effects: Equivalent to memory_­rsrc->deallocate(p, nbytes, alignment).
template<class T> [[nodiscard]] T* allocate_object(size_t n = 1);
Effects: Allocates memory suitable for holding an array of n objects of type T, as follows:
  • if numeric_­limits<size_­t>​::​max() / sizeof(T) < n, throws bad_­array_­new_­length,
  • otherwise equivalent to:
    return static_cast<T*>(allocate_bytes(n*sizeof(T), alignof(T)));
    
Note
:
T is not deduced and must therefore be provided as a template argument.
— end note
 ]
template<class T> void deallocate_object(T* p, size_t n = 1);
Effects: Equivalent to deallocate_­bytes(p, n*sizeof(T), alignof(T)).
template<class T, class CtorArgs...> [[nodiscard]] T* new_object(CtorArgs&&... ctor_args);
Effects: Allocates and constructs an object of type T, as follows.

Equivalent to:
T* p = allocate_object<T>();
try {
  construct(p, std::forward<CtorArgs>(ctor_args)...);
} catch (...) {
  deallocate_object(p);
  throw;
}
return p;
Note
:
T is not deduced and must therefore be provided as a template argument.
— end note
 ]
template<class T> void delete_object(T* p);
Effects: Equivalent to:
destroy(p);
deallocate_object(p);
template<class T, class... Args> void construct(T* p, Args&&... args);
Mandates: Uses-allocator construction of T with allocator *this (see [allocator.uses.construction]) and constructor arguments std​::​forward<Args>(args)... is well-formed.
Effects: Construct a T object in the storage whose address is represented by p by uses-allocator construction with allocator *this and constructor arguments std​::​forward<Args>(args)....
Throws: Nothing unless the constructor for T throws.
template<class T> void destroy(T* p);
Effects: As if by p->~T().
polymorphic_allocator select_on_container_copy_construction() const;
Returns: polymorphic_­allocator().
Note
:
The memory resource is not propagated.
— end note
 ]
memory_resource* resource() const;
Returns: memory_­rsrc.

20.12.3.3 Equality [mem.poly.allocator.eq]

template<class T1, class T2> bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) noexcept;
Returns: *a.resource() == *b.resource().

20.12.4 Access to program-wide memory_­resource objects [mem.res.global]

memory_resource* new_delete_resource() noexcept;
Returns: A pointer to a static-duration object of a type derived from memory_­resource that can serve as a resource for allocating memory using ​::​operator new and ​::​operator delete.
The same value is returned every time this function is called.
For a return value p and a memory resource r, p->is_­equal(r) returns &r == p.
memory_resource* null_memory_resource() noexcept;
Returns: A pointer to a static-duration object of a type derived from memory_­resource for which allocate() always throws bad_­alloc and for which deallocate() has no effect.
The same value is returned every time this function is called.
For a return value p and a memory resource r, p->is_­equal(r) returns &r == p.
The default memory resource pointer is a pointer to a memory resource that is used by certain facilities when an explicit memory resource is not supplied through the interface.
Its initial value is the return value of new_­delete_­resource().
memory_resource* set_default_resource(memory_resource* r) noexcept;
Effects: If r is non-null, sets the value of the default memory resource pointer to r, otherwise sets the default memory resource pointer to new_­delete_­resource().
Returns: The previous value of the default memory resource pointer.
Remarks: Calling the set_­default_­resource and get_­default_­resource functions shall not incur a data race.
A call to the set_­default_­resource function shall synchronize with subsequent calls to the set_­default_­resource and get_­default_­resource functions.
memory_resource* get_default_resource() noexcept;
Returns: The current value of the default memory resource pointer.

20.12.5 Pool resource classes [mem.res.pool]

20.12.5.1 Classes synchronized_­pool_­resource and unsynchronized_­pool_­resource [mem.res.pool.overview]

The synchronized_­pool_­resource and unsynchronized_­pool_­resource classes (collectively called pool resource classes) are general-purpose memory resources having the following qualities:
  • Each resource frees its allocated memory on destruction, even if deallocate has not been called for some of the allocated blocks.
  • A pool resource consists of a collection of pools, serving requests for different block sizes. Each individual pool manages a collection of chunks that are in turn divided into blocks of uniform size, returned via calls to do_­allocate. Each call to do_­allocate(size, alignment) is dispatched to the pool serving the smallest blocks accommodating at least size bytes.
  • When a particular pool is exhausted, allocating a block from that pool results in the allocation of an additional chunk of memory from the upstream allocator (supplied at construction), thus replenishing the pool. With each successive replenishment, the chunk size obtained increases geometrically.
    Note
    : By allocating memory in chunks, the pooling strategy increases the chance that consecutive allocations will be close together in memory. — end note
     ]
  • Allocation requests that exceed the largest block size of any pool are fulfilled directly from the upstream allocator.
  • A pool_­options struct may be passed to the pool resource constructors to tune the largest block size and the maximum chunk size.
A synchronized_­pool_­resource may be accessed from multiple threads without external synchronization and may have thread-specific pools to reduce synchronization costs.
An unsynchronized_­pool_­resource class may not be accessed from multiple threads simultaneously and thus avoids the cost of synchronization entirely in single-threaded applications.
namespace std::pmr {
  struct pool_options {
    size_t max_blocks_per_chunk = 0;
    size_t largest_required_pool_block = 0;
  };

  class synchronized_pool_resource : public memory_resource {
  public:
    synchronized_pool_resource(const pool_options& opts, memory_resource* upstream);

    synchronized_pool_resource()
        : synchronized_pool_resource(pool_options(), get_default_resource()) {}
    explicit synchronized_pool_resource(memory_resource* upstream)
        : synchronized_pool_resource(pool_options(), upstream) {}
    explicit synchronized_pool_resource(const pool_options& opts)
        : synchronized_pool_resource(opts, get_default_resource()) {}

    synchronized_pool_resource(const synchronized_pool_resource&) = delete;
    virtual ~synchronized_pool_resource();

    synchronized_pool_resource& operator=(const synchronized_pool_resource&) = delete;

    void release();
    memory_resource* upstream_resource() const;
    pool_options options() const;

  protected:
    void* do_allocate(size_t bytes, size_t alignment) override;
    void do_deallocate(void* p, size_t bytes, size_t alignment) override;

    bool do_is_equal(const memory_resource& other) const noexcept override;
  };

  class unsynchronized_pool_resource : public memory_resource {
  public:
    unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream);

    unsynchronized_pool_resource()
        : unsynchronized_pool_resource(pool_options(), get_default_resource()) {}
    explicit unsynchronized_pool_resource(memory_resource* upstream)
        : unsynchronized_pool_resource(pool_options(), upstream) {}
    explicit unsynchronized_pool_resource(const pool_options& opts)
        : unsynchronized_pool_resource(opts, get_default_resource()) {}

    unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete;
    virtual ~unsynchronized_pool_resource();

    unsynchronized_pool_resource& operator=(const unsynchronized_pool_resource&) = delete;

    void release();
    memory_resource* upstream_resource() const;
    pool_options options() const;

  protected:
    void* do_allocate(size_t bytes, size_t alignment) override;
    void do_deallocate(void* p, size_t bytes, size_t alignment) override;

    bool do_is_equal(const memory_resource& other) const noexcept override;
  };
}

20.12.5.2 pool_­options data members [mem.res.pool.options]

The members of pool_­options comprise a set of constructor options for pool resources.
The effect of each option on the pool resource behavior is described below:
size_t max_blocks_per_chunk;
The maximum number of blocks that will be allocated at once from the upstream memory resource ([mem.res.monotonic.buffer]) to replenish a pool.
If the value of max_­blocks_­per_­chunk is zero or is greater than an implementation-defined limit, that limit is used instead.
The implementation may choose to use a smaller value than is specified in this field and may use different values for different pools.
size_t largest_required_pool_block;
The largest allocation size that is required to be fulfilled using the pooling mechanism.
Attempts to allocate a single block larger than this threshold will be allocated directly from the upstream memory resource.
If largest_­required_­pool_­block is zero or is greater than an implementation-defined limit, that limit is used instead.
The implementation may choose a pass-through threshold larger than specified in this field.

20.12.5.3 Constructors and destructors [mem.res.pool.ctor]

synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
Preconditions: upstream is the address of a valid memory resource.
Effects: Constructs a pool resource object that will obtain memory from upstream whenever the pool resource is unable to satisfy a memory request from its own internal data structures.
The resulting object will hold a copy of upstream, but will not own the resource to which upstream points.
Note
:
The intention is that calls to upstream->allocate() will be substantially fewer than calls to this->allocate() in most cases.
— end note
 ]
The behavior of the pooling mechanism is tuned according to the value of the opts argument.
Throws: Nothing unless upstream->allocate() throws.
It is unspecified if, or under what conditions, this constructor calls upstream->allocate().
virtual ~synchronized_pool_resource(); virtual ~unsynchronized_pool_resource();
Effects: Calls release().

20.12.5.4 Members [mem.res.pool.mem]

void release();
Effects: Calls upstream_­resource()->deallocate() as necessary to release all allocated memory.
Note
:
The memory is released back to upstream_­resource() even if deallocate has not been called for some of the allocated blocks.
— end note
 ]
memory_resource* upstream_resource() const;
Returns: The value of the upstream argument provided to the constructor of this object.
pool_options options() const;
Returns: The options that control the pooling behavior of this resource.
The values in the returned struct may differ from those supplied to the pool resource constructor in that values of zero will be replaced with implementation-defined defaults, and sizes may be rounded to unspecified granularity.
void* do_allocate(size_t bytes, size_t alignment) override;
Returns: A pointer to allocated storage ([basic.stc.dynamic.allocation]) with a size of at least bytes.
The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_­resource ([mem.res.class]).
Effects: If the pool selected for a block of size bytes is unable to satisfy the memory request from its own internal data structures, it will call upstream_­resource()->allocate() to obtain more memory.
If bytes is larger than that which the largest pool can handle, then memory will be allocated using upstream_­resource()->allocate().
Throws: Nothing unless upstream_­resource()->allocate() throws.
void do_deallocate(void* p, size_t bytes, size_t alignment) override;
Effects: Returns the memory at p to the pool.
It is unspecified if, or under what circumstances, this operation will result in a call to upstream_­resource()->deallocate().
Throws: Nothing.
bool do_is_equal(const memory_resource& other) const noexcept override;
Returns: this == &other.

20.12.6 Class monotonic_­buffer_­resource [mem.res.monotonic.buffer]

A monotonic_­buffer_­resource is a special-purpose memory resource intended for very fast memory allocations in situations where memory is used to build up a few objects and then is released all at once when the memory resource object is destroyed.
It has the following qualities:
  • A call to deallocate has no effect, thus the amount of memory consumed increases monotonically until the resource is destroyed.
  • The program can supply an initial buffer, which the allocator uses to satisfy memory requests.
  • When the initial buffer (if any) is exhausted, it obtains additional buffers from an upstream memory resource supplied at construction. Each additional buffer is larger than the previous one, following a geometric progression.
  • It is intended for access from one thread of control at a time. Specifically, calls to allocate and deallocate do not synchronize with one another.
  • It frees the allocated memory on destruction, even if deallocate has not been called for some of the allocated blocks.
namespace std::pmr {
  class monotonic_buffer_resource : public memory_resource {
    memory_resource* upstream_rsrc;     // exposition only
    void* current_buffer;               // exposition only
    size_t next_buffer_size;            // exposition only

  public:
    explicit monotonic_buffer_resource(memory_resource* upstream);
    monotonic_buffer_resource(size_t initial_size, memory_resource* upstream);
    monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream);

    monotonic_buffer_resource()
      : monotonic_buffer_resource(get_default_resource()) {}
    explicit monotonic_buffer_resource(size_t initial_size)
      : monotonic_buffer_resource(initial_size, get_default_resource()) {}
    monotonic_buffer_resource(void* buffer, size_t buffer_size)
      : monotonic_buffer_resource(buffer, buffer_size, get_default_resource()) {}

    monotonic_buffer_resource(const monotonic_buffer_resource&) = delete;

    virtual ~monotonic_buffer_resource();

    monotonic_buffer_resource& operator=(const monotonic_buffer_resourc