%!TEX root = std.tex
\rSec0[mem]{Memory management library}

\rSec1[mem.general]{General}

\pnum
This Clause describes components for memory management.

\pnum
The following subclauses describe general memory management facilities,
smart pointers, memory resources, and scoped allocators,
as summarized in \tref{mem.summary}.

\begin{libsumtab}{Memory management library summary}{mem.summary}
\ref{memory}                & Memory                            & \tcode{<cstdlib>}, \tcode{<memory>} \\ \rowsep
\ref{smartptr}              & Smart pointers                    & \tcode{<memory>}           \\ \rowsep
\ref{mem.composite.types}   & Types for composite class design  & \tcode{<memory>}           \\ \rowsep
\ref{mem.res}               & Memory resources                  & \tcode{<memory_resource>}  \\ \rowsep
\ref{allocator.adaptor}     & Scoped allocators                 & \tcode{<scoped_allocator>} \\
\end{libsumtab}

\rSec1[memory]{Memory}

\rSec2[memory.general]{General}

\pnum
Subclause~\ref{memory} describes the contents of the header
\libheaderref{memory} and some
of the contents of the header \libheaderref{cstdlib}.

\rSec2[memory.syn]{Header \tcode{<memory>} synopsis}

\pnum
The header \libheaderdef{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~(\ref{pointer.traits}--\ref{specialized.addressof} and \ref{specialized.algorithms}).
The header also defines the templates
\tcode{unique_ptr}, \tcode{shared_ptr}, \tcode{weak_ptr},
\tcode{out_ptr_t}, \tcode{inout_ptr_t}, and various function
templates that operate on objects of these types\iref{smartptr}.

\pnum
Let \tcode{\exposid{POINTER_OF}(T)} denote a type that is
\begin{itemize}
\item
\tcode{T::pointer} if the \grammarterm{qualified-id} \tcode{T::pointer}
is valid and denotes a type,
\item
otherwise, \tcode{T::element_type*}
if the \grammarterm{qualified-id} \tcode{T::element_type}
is valid and denotes a type,
\item
otherwise, \tcode{pointer_traits<T>::element_type*}.
\end{itemize}

\pnum
Let \tcode{\exposid{POINTER_OF_OR}(T, U)} denote a type that is:
\begin{itemize}
\item
\tcode{\exposid{POINTER_OF}(T)}
if \tcode{\exposid{POINTER_OF}(T)} is valid and denotes a type,
\item
otherwise, \tcode{U}.
\end{itemize}

\begin{codeblock}
#include <compare>              // see \ref{compare.syn}

namespace std {
  // \ref{pointer.traits}, pointer traits
  template<class Ptr> struct pointer_traits;                                        // freestanding
  template<class T> struct pointer_traits<T*>;                                      // freestanding

  // \ref{pointer.conversion}, pointer conversion
  template<class T>
    constexpr T* to_address(T* p) noexcept;                                         // freestanding
  template<class Ptr>
    constexpr auto to_address(const Ptr& p) noexcept;                               // freestanding

  // \ref{ptr.align}, pointer alignment
  void* align(size_t alignment, size_t size, void*& ptr, size_t& space);            // freestanding
  template<size_t N, class T>
    constexpr T* assume_aligned(T* ptr);                                            // freestanding
  template<size_t Alignment, class T>
    bool is_sufficiently_aligned(T* ptr);                                           // freestanding

  // \ref{obj.lifetime}, explicit lifetime management
  template<class T>
    constexpr void start_lifetime(T& r) noexcept;                                   // freestanding
  template<class T>
    T* start_lifetime_as(void* p) noexcept;                                         // freestanding
  template<class T>
    const T* start_lifetime_as(const void* p) noexcept;                             // freestanding
  template<class T>
    volatile T* start_lifetime_as(volatile void* p) noexcept;                       // freestanding
  template<class T>
    const volatile T* start_lifetime_as(const volatile void* p) noexcept;           // freestanding
  template<class T>
    T* start_lifetime_as_array(void* p, size_t n) noexcept;                         // freestanding
  template<class T>
    const T* start_lifetime_as_array(const void* p, size_t n) noexcept;             // freestanding
  template<class T>
    volatile T* start_lifetime_as_array(volatile void* p, size_t n) noexcept;       // freestanding
  template<class T>
    const volatile T* start_lifetime_as_array(const volatile void* p,               // freestanding
	                                      size_t n) noexcept;

  // \ref{allocator.tag}, allocator argument tag
  struct allocator_arg_t { explicit allocator_arg_t() = default; };                 // freestanding
  inline constexpr allocator_arg_t allocator_arg{};                                 // freestanding

  // \ref{allocator.uses}, \tcode{uses_allocator}
  template<class T, class Alloc> struct uses_allocator;                             // freestanding

  // \ref{allocator.uses.trait}, \tcode{uses_allocator}
  template<class T, class Alloc>
    constexpr bool @\libglobal{uses_allocator_v}@ = uses_allocator<T, Alloc>::value;              // freestanding

  // \ref{allocator.uses.construction}, uses-allocator construction
  template<class T, class Alloc, class... Args>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,             // freestanding
                                                    Args&&... args) noexcept;
  template<class T, class Alloc, class Tuple1, class Tuple2>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,             // freestanding
                                                    piecewise_construct_t,
                                                    Tuple1&& x, Tuple2&& y) noexcept;
  template<class T, class Alloc>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept;   // freestanding
  template<class T, class Alloc, class U, class V>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,             // freestanding
                                                    U&& u, V&& v) noexcept;
  template<class T, class Alloc, class U, class V>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,             // freestanding
                                                    pair<U, V>& pr) noexcept;
  template<class T, class Alloc, class U, class V>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,             // freestanding
                                                    const pair<U, V>& pr) noexcept;
  template<class T, class Alloc, class U, class V>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,             // freestanding
                                                    pair<U, V>&& pr) noexcept;
  template<class T, class Alloc, class U, class V>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,             // freestanding
                                                    const pair<U, V>&& pr) noexcept;
  template<class T, class Alloc, @\exposconcept{pair-like}@ P>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,             // freestanding
                                                    P&& p) noexcept;
  template<class T, class Alloc, class U>
    constexpr auto uses_allocator_construction_args(const Alloc& alloc,             // freestanding
                                                    U&& u) noexcept;
  template<class T, class Alloc, class... Args>
    constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args);       // freestanding
  template<class T, class Alloc, class... Args>
    constexpr T* uninitialized_construct_using_allocator(T* p,                      // freestanding
                                                         const Alloc& alloc, Args&&... args);

  // \ref{allocator.traits}, allocator traits
  template<class Alloc> struct allocator_traits;                                    // freestanding

  template<class Pointer, class SizeType = size_t>
  struct @\libglobal{allocation_result}@ {                                                        // freestanding
    Pointer @\libmember{ptr}{allocation_result}@;
    SizeType @\libmember{count}{allocation_result}@;
  };

  // \ref{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;

  // \ref{specialized.addressof}, addressof
  template<class T>
    constexpr T* addressof(T& r) noexcept;                                          // freestanding
  template<class T>
    const T* addressof(const T&&) = delete;                                         // freestanding

  // \ref{specialized.algorithms}, specialized algorithms
  // \ref{special.mem.concepts}, special memory concepts
  template<class I>
    concept @\exposconcept{nothrow-input-iterator}@ = @\seebelow@;                // \expos
  template<class I>
    concept @\exposconcept{nothrow-forward-iterator}@ = @\seebelow@;              // \expos
  template<class I>
    concept @\exposconcept{nothrow-bidirectional-iterator}@ = @\seebelow@;        // \expos
  template<class I>
    concept @\exposconcept{nothrow-random-access-iterator}@ = @\seebelow@;        // \expos
  template<class S, class I>
    concept @\exposconcept{nothrow-sentinel-for}@ = @\seebelow@;                  // \expos
  template<class S, class I>
    concept @\exposconcept{nothrow-sized-sentinel-for}@ = @\seebelow@;            // \expos
  template<class R>
    concept @\exposconcept{nothrow-input-range}@ = @\seebelow@;                   // \expos
  template<class R>
    concept @\exposconcept{nothrow-forward-range}@ = @\seebelow@;                 // \expos
  template<class R>
    concept @\exposconcept{nothrow-bidirectional-range}@ = @\seebelow@;           // \expos
  template<class R>
    concept @\exposconcept{nothrow-random-access-range}@ = @\seebelow@;           // \expos
  template<class R>
    concept @\exposconcept{nothrow-sized-random-access-range}@ = @\seebelow@;     // \expos

  template<class NoThrowForwardIterator>
    constexpr void uninitialized_default_construct(NoThrowForwardIterator first,    // freestanding
                                                   NoThrowForwardIterator last);
  template<class ExecutionPolicy, class NoThrowForwardIterator>
    void uninitialized_default_construct(ExecutionPolicy&& exec,            // freestanding-deleted,
                                         NoThrowForwardIterator first,      // see \ref{algorithms.parallel.overloads}
                                         NoThrowForwardIterator last);
  template<class NoThrowForwardIterator, class Size>
    constexpr NoThrowForwardIterator
      uninitialized_default_construct_n(NoThrowForwardIterator first, Size n);      // freestanding
  template<class ExecutionPolicy, class NoThrowForwardIterator, class Size>
    NoThrowForwardIterator
      uninitialized_default_construct_n(ExecutionPolicy&& exec,             // freestanding-deleted,
                                        NoThrowForwardIterator first,       // see \ref{algorithms.parallel.overloads}
                                        Size n);

  namespace ranges {
    template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@<I> S>
      requires @\libconcept{default_initializable}@<iter_value_t<I>>
        constexpr I uninitialized_default_construct(I first, S last);               // freestanding
    template<@\exposconcept{nothrow-forward-range}@ R>
      requires @\libconcept{default_initializable}@<range_value_t<R>>
        constexpr borrowed_iterator_t<R> uninitialized_default_construct(R&& r);    // freestanding

    template<@\exposconcept{nothrow-forward-iterator}@ I>
      requires @\libconcept{default_initializable}@<iter_value_t<I>>
        constexpr I uninitialized_default_construct_n(I first,                      // freestanding
                                                      iter_difference_t<I> n);

    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I,
             @\exposconcept{nothrow-sized-sentinel-for}@<I> S>
      requires @\libconcept{default_initializable}@<iter_value_t<I>>
        I uninitialized_default_construct(Ep&& exec, I first, S last);      // freestanding-deleted,
                                                                            // see \ref{algorithms.parallel.overloads}
    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R>
      requires @\libconcept{default_initializable}@<range_value_t<R>>
        borrowed_iterator_t<R> uninitialized_default_construct(Ep&& exec,   // freestanding-deleted,
                                                               R&& r);      // see \ref{algorithms.parallel.overloads}

    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I>
      requires @\libconcept{default_initializable}@<iter_value_t<I>>
        I uninitialized_default_construct_n(Ep&& exec, I first,             // freestanding-deleted,
                                            iter_difference_t<I> n);        // see \ref{algorithms.parallel.overloads}
  }

  template<class NoThrowForwardIterator>
    constexpr void uninitialized_value_construct(NoThrowForwardIterator first,      // freestanding
                                                 NoThrowForwardIterator last);
  template<class ExecutionPolicy, class NoThrowForwardIterator>
    void uninitialized_value_construct(ExecutionPolicy&& exec,              // freestanding-deleted,
                                       NoThrowForwardIterator first,        // see \ref{algorithms.parallel.overloads}
                                       NoThrowForwardIterator last);
  template<class NoThrowForwardIterator, class Size>
    constexpr NoThrowForwardIterator
      uninitialized_value_construct_n(NoThrowForwardIterator first, Size n);        // freestanding
  template<class ExecutionPolicy, class NoThrowForwardIterator, class Size>
    NoThrowForwardIterator
      uninitialized_value_construct_n(ExecutionPolicy&& exec,               // freestanding-deleted,
                                      NoThrowForwardIterator first,         // see \ref{algorithms.parallel.overloads}
                                      Size n);

  namespace ranges {
    template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@<I> S>
      requires @\libconcept{default_initializable}@<iter_value_t<I>>
        constexpr I uninitialized_value_construct(I first, S last);                 // freestanding
    template<@\exposconcept{nothrow-forward-range}@ R>
      requires @\libconcept{default_initializable}@<range_value_t<R>>
        constexpr borrowed_iterator_t<R> uninitialized_value_construct(R&& r);      // freestanding

    template<@\exposconcept{nothrow-forward-iterator}@ I>
      requires @\libconcept{default_initializable}@<iter_value_t<I>>
        constexpr I uninitialized_value_construct_n(I first,                        // freestanding
                                                    iter_difference_t<I> n);

    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I,
             @\exposconcept{nothrow-sized-sentinel-for}@<I> S>
      requires @\libconcept{default_initializable}@<iter_value_t<I>>
        I uninitialized_value_construct(Ep&& exec, I first, S last);        // freestanding-deleted,
                                                                            // see \ref{algorithms.parallel.overloads}
    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R>
      requires @\libconcept{default_initializable}@<range_value_t<R>>
        borrowed_iterator_t<R> uninitialized_value_construct(Ep&& exec,     // freestanding-deleted,
                                                             R&& r);        // see \ref{algorithms.parallel.overloads}

    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I>
      requires @\libconcept{default_initializable}@<iter_value_t<I>>
        I uninitialized_value_construct_n(Ep&& exec, I first,               // freestanding-deleted,
                                          iter_difference_t<I> n);          // see \ref{algorithms.parallel.overloads}
  }

  template<class InputIterator, class NoThrowForwardIterator>
    constexpr NoThrowForwardIterator uninitialized_copy(InputIterator first,        // freestanding
                                                        InputIterator last,
                                                        NoThrowForwardIterator result);
  template<class ExecutionPolicy, class ForwardIterator, class NoThrowForwardIterator>
    NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec,       // freestanding-deleted,
                                              ForwardIterator first,        // see \ref{algorithms.parallel.overloads}
                                              ForwardIterator last,
                                              NoThrowForwardIterator result);
  template<class InputIterator, class Size, class NoThrowForwardIterator>
    constexpr NoThrowForwardIterator uninitialized_copy_n(InputIterator first,      // freestanding
                                                          Size n,
                                                          NoThrowForwardIterator result);
  template<class ExecutionPolicy, class ForwardIterator, class Size,
           class NoThrowForwardIterator>
    NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec,     // freestanding-deleted,
                                                ForwardIterator first,      // see \ref{algorithms.parallel.overloads}
                                                Size n,
                                                NoThrowForwardIterator result);

  namespace ranges {
    template<class I, class O>
      using @\libglobal{uninitialized_copy_result}@ = in_out_result<I, O>;                        // freestanding
    template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@<I> S1,
             @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@<O> S2>
      requires @\libconcept{constructible_from}@<iter_value_t<O>, iter_reference_t<I>>
        constexpr uninitialized_copy_result<I, O>
          uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast);               // freestanding
    template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR>
      requires @\libconcept{constructible_from}@<range_value_t<OR>, range_reference_t<IR>>
        constexpr uninitialized_copy_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>>
          uninitialized_copy(IR&& in_range, OR&& out_range);                        // freestanding

    template<class I, class O>
      using @\libglobal{uninitialized_copy_n_result}@ = in_out_result<I, O>;                      // freestanding
    template<@\libconcept{input_iterator}@ I, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@<O> S>
      requires @\libconcept{constructible_from}@<iter_value_t<O>, iter_reference_t<I>>
        constexpr uninitialized_copy_n_result<I, O>
          uninitialized_copy_n(I ifirst, iter_difference_t<I> n,                    // freestanding
                               O ofirst, S olast);

    template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S1,
             @\exposconcept{nothrow-random-access-iterator}@ O, @\exposconcept{nothrow-sized-sentinel-for}@<O> S2>
      requires @\libconcept{constructible_from}@<iter_value_t<O>, iter_reference_t<I>>
        uninitialized_copy_result<I, O>
          uninitialized_copy(Ep&& exec, I ifirst, S1 ilast,                 // freestanding-deleted,
                             O ofirst, S2 olast);                           // see \ref{algorithms.parallel.overloads}
    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ IR,
             @\exposconcept{nothrow-sized-random-access-range}@ OR>
      requires @\libconcept{constructible_from}@<range_value_t<OR>, range_reference_t<IR>>
        uninitialized_copy_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>>
          uninitialized_copy(Ep&& exec, IR&& in_range, OR&& out_range);     // freestanding-deleted,
                                                                            // see \ref{algorithms.parallel.overloads}
    template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\exposconcept{nothrow-random-access-iterator}@ O,
             @\exposconcept{nothrow-sized-sentinel-for}@<O> S>
      requires @\libconcept{constructible_from}@<iter_value_t<O>, iter_reference_t<I>>
        uninitialized_copy_n_result<I, O>
          uninitialized_copy_n(Ep&& exec, I ifirst, iter_difference_t<I> n, // freestanding-deleted,
                               O ofirst, S olast);                          // see \ref{algorithms.parallel.overloads}
  }

  template<class InputIterator, class NoThrowForwardIterator>
    constexpr NoThrowForwardIterator uninitialized_move(InputIterator first,        // freestanding
                                                        InputIterator last,
                                                        NoThrowForwardIterator result);
  template<class ExecutionPolicy, class ForwardIterator, class NoThrowForwardIterator>
    NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec,       // freestanding-deleted,
                                              ForwardIterator first,        // see \ref{algorithms.parallel.overloads}
                                              ForwardIterator last,
                                              NoThrowForwardIterator result);
  template<class InputIterator, class Size, class NoThrowForwardIterator>
    constexpr pair<InputIterator, NoThrowForwardIterator>
      uninitialized_move_n(InputIterator first, Size n,                             // freestanding
                           NoThrowForwardIterator result);
  template<class ExecutionPolicy, class ForwardIterator, class Size,
           class NoThrowForwardIterator>
    pair<ForwardIterator, NoThrowForwardIterator>
      uninitialized_move_n(ExecutionPolicy&& exec,                          // freestanding-deleted,
                           ForwardIterator first, Size n,                   // see \ref{algorithms.parallel.overloads}
                           NoThrowForwardIterator result);

  namespace ranges {
    template<class I, class O>
      using @\libglobal{uninitialized_move_result}@ = in_out_result<I, O>;                        // freestanding
    template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@<I> S1,
             @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@<O> S2>
      requires @\libconcept{constructible_from}@<iter_value_t<O>, iter_rvalue_reference_t<I>>
        constexpr uninitialized_move_result<I, O>
          uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast);               // freestanding
    template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR>
      requires @\libconcept{constructible_from}@<range_value_t<OR>, range_rvalue_reference_t<IR>>
        constexpr uninitialized_move_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>>
          uninitialized_move(IR&& in_range, OR&& out_range);                        // freestanding

    template<class I, class O>
      using @\libglobal{uninitialized_move_n_result}@ = in_out_result<I, O>;                      // freestanding
    template<@\libconcept{input_iterator}@ I,
             @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@<O> S>
      requires @\libconcept{constructible_from}@<iter_value_t<O>, iter_rvalue_reference_t<I>>
        constexpr uninitialized_move_n_result<I, O>
          uninitialized_move_n(I ifirst, iter_difference_t<I> n,                    // freestanding
                               O ofirst, S olast);

    template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S1,
             @\exposconcept{nothrow-random-access-iterator}@ O, @\exposconcept{nothrow-sized-sentinel-for}@<O> S2>
      requires @\libconcept{constructible_from}@<iter_value_t<O>, iter_rvalue_reference_t<I>>
        uninitialized_move_result<I, O>
          uninitialized_move(Ep&& exec, I ifirst, S1 ilast,                 // freestanding-deleted,
                             O ofirst, S2 olast);                           // see \ref{algorithms.parallel.overloads}
    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ IR,
             @\exposconcept{nothrow-sized-random-access-range}@ OR>
      requires @\libconcept{constructible_from}@<range_value_t<OR>, range_rvalue_reference_t<IR>>
        uninitialized_move_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>>
          uninitialized_move(Ep&& exec, IR&& in_range, OR&& out_range);     // freestanding-deleted,
                                                                            // see \ref{algorithms.parallel.overloads}

    template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I,
             @\exposconcept{nothrow-random-access-iterator}@ O, @\exposconcept{nothrow-sized-sentinel-for}@<O> S>
      requires @\libconcept{constructible_from}@<iter_value_t<O>, iter_rvalue_reference_t<I>>
        uninitialized_move_n_result<I, O>
          uninitialized_move_n(Ep&& exec, I ifirst, iter_difference_t<I> n, // freestanding-deleted,
                               O ofirst, S olast);                          // see \ref{algorithms.parallel.overloads}
  }

  template<class NoThrowForwardIterator,
           class T = iterator_traits<NoThrowForwardIterator>::value_type>
    constexpr void uninitialized_fill(NoThrowForwardIterator first,                 // freestanding
                                      NoThrowForwardIterator last, const T& x);
  template<class ExecutionPolicy, class NoThrowForwardIterator,
           class T = iterator_traits<NoThrowForwardIterator>::value_type>
    void uninitialized_fill(ExecutionPolicy&& exec,                         // freestanding-deleted,
                            NoThrowForwardIterator first,                   // see \ref{algorithms.parallel.overloads}
                            NoThrowForwardIterator last,
                            const T& x);
  template<class NoThrowForwardIterator, class Size,
           class T = iterator_traits<NoThrowForwardIterator>::value_type>
    constexpr NoThrowForwardIterator
      uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x);       // freestanding
  template<class ExecutionPolicy, class NoThrowForwardIterator, class Size,
           class T = iterator_traits<NoThrowForwardIterator>::value_type>
    NoThrowForwardIterator
      uninitialized_fill_n(ExecutionPolicy&& exec,                          // freestanding-deleted,
                           NoThrowForwardIterator first,                    // see \ref{algorithms.parallel.overloads}
                           Size n, const T& x);

  namespace ranges {
    template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@<I> S, class T = iter_value_t<I>>
      requires @\libconcept{constructible_from}@<iter_value_t<I>, const T&>
        constexpr I uninitialized_fill(I first, S last, const T& x);                // freestanding
    template<@\exposconcept{nothrow-forward-range}@ R, class T = range_value_t<R>>
      requires @\libconcept{constructible_from}@<range_value_t<R>, const T&>
        constexpr borrowed_iterator_t<R> uninitialized_fill(R&& r, const T& x);     // freestanding

    template<@\exposconcept{nothrow-forward-iterator}@ I, class T = iter_value_t<I>>
      requires @\libconcept{constructible_from}@<iter_value_t<I>, const T&>
        constexpr I uninitialized_fill_n(I first,                                   // freestanding
                                         iter_difference_t<I> n, const T& x);

    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I,
             @\exposconcept{nothrow-sized-sentinel-for}@<I> S, class T = iter_value_t<I>>
      requires @\libconcept{constructible_from}@<iter_value_t<I>, const T&>
        I uninitialized_fill(Ep&& exec, I first, S last, const T& x);       // freestanding-deleted,
                                                                            // see \ref{algorithms.parallel.overloads}
    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R,
             class T = range_value_t<R>>
      requires @\libconcept{constructible_from}@<range_value_t<R>, const T&>
        borrowed_iterator_t<R> uninitialized_fill(Ep&& exec, R&& r,         // freestanding-deleted,
                                                  const T& x);              // see \ref{algorithms.parallel.overloads}

    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I, class T = iter_value_t<I>>
      requires @\libconcept{constructible_from}@<iter_value_t<I>, const T&>
        I uninitialized_fill_n(Ep&& exec, I first,                          // freestanding-deleted,
                               iter_difference_t<I> n, const T& x);         // see \ref{algorithms.parallel.overloads}
  }

  // \ref{specialized.construct}, \tcode{construct_at}
  template<class T, class... Args>
    constexpr T* construct_at(T* location, Args&&... args);                         // freestanding

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

  // \ref{specialized.destroy}, \tcode{destroy}
  template<class T>
    constexpr void destroy_at(T* location);                                         // freestanding
  template<class NoThrowForwardIterator>
    constexpr void destroy(NoThrowForwardIterator first,                            // freestanding
                           NoThrowForwardIterator last);
  template<class ExecutionPolicy, class NoThrowForwardIterator>
    void destroy(ExecutionPolicy&& exec,                                    // freestanding-deleted,
                 NoThrowForwardIterator first,                              // see \ref{algorithms.parallel.overloads}
                 NoThrowForwardIterator last);
  template<class NoThrowForwardIterator, class Size>
    constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first,        // freestanding
                                               Size n);
  template<class ExecutionPolicy, class NoThrowForwardIterator, class Size>
    NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec,                // freestanding-deleted,
                                     NoThrowForwardIterator first, Size n); // see \ref{algorithms.parallel.overloads}

  namespace ranges {
    template<@\libconcept{destructible}@ T>
      constexpr void destroy_at(T* location) noexcept;                              // freestanding

    template<@\exposconcept{nothrow-input-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@<I> S>
      requires @\libconcept{destructible}@<iter_value_t<I>>
        constexpr I destroy(I first, S last) noexcept;                              // freestanding
    template<@\exposconcept{nothrow-input-range}@ R>
      requires @\libconcept{destructible}@<range_value_t<R>>
        constexpr borrowed_iterator_t<R> destroy(R&& r) noexcept;                   // freestanding

    template<@\exposconcept{nothrow-input-iterator}@ I>
      requires @\libconcept{destructible}@<iter_value_t<I>>
        constexpr I destroy_n(I first, iter_difference_t<I> n) noexcept;            // freestanding

    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I,
             @\exposconcept{nothrow-sized-sentinel-for}@<I> S>
      requires @\libconcept{destructible}@<iter_value_t<I>>
        I destroy(Ep&& exec, I first, S last);                              // freestanding-deleted,
                                                                            // see \ref{algorithms.parallel.overloads}
    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R>
      requires @\libconcept{destructible}@<range_value_t<R>>
        borrowed_iterator_t<R> destroy(Ep&& exec, R&& r);                   // freestanding-deleted,
                                                                            // see \ref{algorithms.parallel.overloads}
    template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I>
      requires @\libconcept{destructible}@<iter_value_t<I>>
        I destroy_n(Ep&& exec, I first, iter_difference_t<I> n);            // freestanding-deleted,
                                                                            // see \ref{algorithms.parallel.overloads}
  }

  // \ref{unique.ptr}, class template \tcode{unique_ptr}
  template<class T> struct default_delete;                                          // freestanding
  template<class T> struct default_delete<T[]>;                                     // freestanding
  template<class T, class D = default_delete<T>> class unique_ptr;                  // freestanding
  template<class T, class D> class unique_ptr<T[], D>;                              // freestanding

  template<class T, class... Args>
    constexpr unique_ptr<T> make_unique(Args&&... args);                        // \tcode{T} is not array
  template<class T>
    constexpr unique_ptr<T> make_unique(size_t n);                              // \tcode{T} is \tcode{U[]}
  template<class T, class... Args>
    @\unspecnc@ make_unique(Args&&...) = delete;                                // \tcode{T} is \tcode{U[N]}

  template<class T>
    constexpr unique_ptr<T> make_unique_for_overwrite();                        // \tcode{T} is not array
  template<class T>
    constexpr unique_ptr<T> make_unique_for_overwrite(size_t n);                // \tcode{T} is \tcode{U[]}
  template<class T, class... Args>
    @\unspecnc@ make_unique_for_overwrite(Args&&...) = delete;                  // \tcode{T} is \tcode{U[N]}

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

  template<class T1, class D1, class T2, class D2>
    constexpr bool operator==(const unique_ptr<T1, D1>& x,                          // freestanding
                              const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    constexpr bool operator<(const unique_ptr<T1, D1>& x,                           // freestanding
                             const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    constexpr bool operator>(const unique_ptr<T1, D1>& x,                           // freestanding
                             const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    constexpr bool operator<=(const unique_ptr<T1, D1>& x,                          // freestanding
                              const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    constexpr bool operator>=(const unique_ptr<T1, D1>& x,                          // freestanding
                              const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    requires @\libconcept{three_way_comparable_with}@<typename unique_ptr<T1, D1>::pointer,
                                       typename unique_ptr<T2, D2>::pointer>
    constexpr 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);        // freestanding

  template<class T, class D>
    constexpr bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;       // freestanding
  template<class T, class D>
    constexpr bool operator<(const unique_ptr<T, D>& x, nullptr_t);                 // freestanding
  template<class T, class D>
    constexpr bool operator<(nullptr_t, const unique_ptr<T, D>& y);                 // freestanding
  template<class T, class D>
    constexpr bool operator>(const unique_ptr<T, D>& x, nullptr_t);                 // freestanding
  template<class T, class D>
    constexpr bool operator>(nullptr_t, const unique_ptr<T, D>& y);                 // freestanding
  template<class T, class D>
    constexpr bool operator<=(const unique_ptr<T, D>& x, nullptr_t);                // freestanding
  template<class T, class D>
    constexpr bool operator<=(nullptr_t, const unique_ptr<T, D>& y);                // freestanding
  template<class T, class D>
    constexpr bool operator>=(const unique_ptr<T, D>& x, nullptr_t);                // freestanding
  template<class T, class D>
    constexpr bool operator>=(nullptr_t, const unique_ptr<T, D>& y);                // freestanding
  template<class T, class D>
    requires @\libconcept{three_way_comparable}@<typename unique_ptr<T, D>::pointer>
    constexpr compare_three_way_result_t<typename unique_ptr<T, D>::pointer>
      operator<=>(const unique_ptr<T, D>& x, nullptr_t);                            // freestanding

  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);

  // \ref{util.smartptr.weak.bad}, class \tcode{bad_weak_ptr}
  class bad_weak_ptr;

  // \ref{util.smartptr.shared}, class template \tcode{shared_ptr}
  template<class T> class shared_ptr;

  // \ref{util.smartptr.shared.create}, \tcode{shared_ptr} creation
  template<class T, class... Args>
    constexpr shared_ptr<T> make_shared(Args&&... args);                        // \tcode{T} is not array
  template<class T, class A, class... Args>
    constexpr shared_ptr<T> allocate_shared(const A& a, Args&&... args);        // \tcode{T} is not array

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

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

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

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

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

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

  // \ref{util.smartptr.shared.cmp}, \tcode{shared_ptr} comparisons
  template<class T, class U>
    constexpr bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    constexpr strong_ordering operator<=>(const shared_ptr<T>& a,
                                          const shared_ptr<U>& b) noexcept;

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

  // \ref{util.smartptr.shared.spec}, \tcode{shared_ptr} specialized algorithms
  template<class T>
    constexpr void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;

  // \ref{util.smartptr.shared.cast}, \tcode{shared_ptr} casts
  template<class T, class U>
    constexpr shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
    constexpr shared_ptr<T> static_pointer_cast(shared_ptr<U>&& r) noexcept;
  template<class T, class U>
    constexpr shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
    constexpr shared_ptr<T> dynamic_pointer_cast(shared_ptr<U>&& r) noexcept;
  template<class T, class U>
    constexpr shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
    constexpr 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;

  // \ref{util.smartptr.getdeleter}, \tcode{shared_ptr} \tcode{get_deleter}
  template<class D, class T>
    constexpr D* get_deleter(const shared_ptr<T>& p) noexcept;

  // \ref{util.smartptr.shared.io}, \tcode{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);

  // \ref{util.smartptr.weak}, class template \tcode{weak_ptr}
  template<class T> class weak_ptr;

  // \ref{util.smartptr.weak.spec}, \tcode{weak_ptr} specialized algorithms
  template<class T> constexpr void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;

  // \ref{util.smartptr.ownerless}, class template \tcode{owner_less}
  template<class T = void> struct owner_less;

  // \ref{util.smartptr.owner.hash}, struct \tcode{owner_hash}
  struct owner_hash;

  // \ref{util.smartptr.owner.equal}, struct \tcode{owner_equal}
  struct owner_equal;

  // \ref{util.smartptr.enab}, class template \tcode{enable_shared_from_this}
  template<class T> class enable_shared_from_this;

  // \ref{util.smartptr.hash}, hash support
  template<class T> struct hash;                                                    // freestanding
  template<class T, class D> struct hash<unique_ptr<T, D>>;                         // freestanding
  template<class T> struct hash<shared_ptr<T>>;

  // \ref{util.smartptr.atomic}, atomic smart pointers
  template<class T> struct atomic;                                                  // freestanding
  template<class T> struct atomic<shared_ptr<T>>;
  template<class T> struct atomic<weak_ptr<T>>;

  // \ref{out.ptr.t}, class template \tcode{out_ptr_t}
  template<class Smart, class Pointer, class... Args>
    class out_ptr_t;                                                                // freestanding

  // \ref{out.ptr}, function template \tcode{out_ptr}
  template<class Pointer = void, class Smart, class... Args>
    constexpr auto out_ptr(Smart& s, Args&&... args);                               // freestanding

  // \ref{inout.ptr.t}, class template \tcode{inout_ptr_t}
  template<class Smart, class Pointer, class... Args>
    class inout_ptr_t;                                                              // freestanding

  // \ref{inout.ptr}, function template \tcode{inout_ptr}
  template<class Pointer = void, class Smart, class... Args>
    constexpr auto inout_ptr(Smart& s, Args&&... args);                             // freestanding

  // \ref{indirect}, class template \tcode{indirect}
  template<class T, class Allocator = allocator<T>>
    class indirect;

  // \ref{indirect.hash}, hash support
  template<class T, class Alloc> struct hash<indirect<T, Alloc>>;

  // \ref{polymorphic}, class template \tcode{polymorphic}
  template<class T, class Allocator = allocator<T>>
    class polymorphic;

  namespace pmr {
    template<class T> using indirect    = indirect<T, polymorphic_allocator<T>>;
    template<class T> using polymorphic = polymorphic<T, polymorphic_allocator<T>>;
  }
}
\end{codeblock}

\rSec2[pointer.traits]{Pointer traits}

\rSec3[pointer.traits.general]{General}

\pnum
The class template \tcode{pointer_traits} supplies a uniform interface to certain
attributes of pointer-like types.

\indexlibraryglobal{pointer_traits}%
\begin{codeblock}
namespace std {
  template<class Ptr> struct pointer_traits {
    @\seebelow@;
  };

  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(@\seebelow@ r) noexcept;
  };
}
\end{codeblock}

\rSec3[pointer.traits.types]{Member types}

\pnum
The definitions in this subclause make use of
the following exposition-only class template and concept:
\begin{codeblock}
template<class T>
struct @\exposid{ptr-traits-elem}@          // \expos
{ };

template<class T> requires requires { typename T::element_type; }
struct @\exposid{ptr-traits-elem}@<T>
{ using type = T::element_type; };

template<template<class...> class SomePointer, class T, class... Args>
  requires (!requires { typename SomePointer<T, Args...>::element_type; })
struct @\exposid{ptr-traits-elem}@<SomePointer<T, Args...>>
{ using type = T; };

template<class Ptr>
  concept @\defexposconcept{has-elem-type}@ =       // \expos
    requires { typename @\exposid{ptr-traits-elem}@<Ptr>::type; }
\end{codeblock}

\pnum
If \tcode{Ptr} satisfies \exposconcept{has-elem-type},
a specialization \tcode{pointer_traits<Ptr>}
generated from the \tcode{pointer_traits} primary template
has the following members
as well as those described in~\ref{pointer.traits.functions};
otherwise, such a specialization has no members by any of those names.

\indexlibrarymember{pointer}{pointer_traits}%
\begin{itemdecl}
using pointer = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Ptr}.
\end{itemdescr}

\indexlibrarymember{element_type}{pointer_traits}%
\begin{itemdecl}
using element_type = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{typename \exposid{ptr-traits-elem}<Ptr>::type}.
\end{itemdescr}

\indexlibrarymember{difference_type}{pointer_traits}%
\begin{itemdecl}
using difference_type = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Ptr::difference_type} if
the \grammarterm{qualified-id} \tcode{Ptr::difference_type} is valid and denotes a
type\iref{temp.deduct}; otherwise,
\tcode{ptrdiff_t}.
\end{itemdescr}

\indexlibrarymember{rebind}{pointer_traits}%
\begin{itemdecl}
template<class U> using rebind = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\templalias \tcode{Ptr::rebind<U>} if
the \grammarterm{qualified-id} \tcode{Ptr::rebind<U>} is valid and denotes a
type\iref{temp.deduct}; otherwise,
\tcode{SomePointer<U, Args>} if
\tcode{Ptr} is a class template specialization of the form \tcode{SomePointer<T, Args>},
where \tcode{Args} is zero or more type arguments; otherwise, the instantiation of
\tcode{rebind} is ill-formed.
\end{itemdescr}

\rSec3[pointer.traits.functions]{Member functions}

\indexlibrarymember{pointer_to}{pointer_traits}%
\begin{itemdecl}
static constexpr pointer pointer_traits::pointer_to(@\seebelow@ r);
static constexpr pointer pointer_traits<T*>::pointer_to(@\seebelow@ r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
For the first member function,
\tcode{Ptr::pointer_to(r)} is well-formed.

\pnum
\expects
For the first member function,
\tcode{Ptr::pointer_to(r)} returns a pointer to \tcode{r}
through which indirection is valid.

\pnum
\returns
The first member function returns \tcode{Ptr::pointer_to(r)}.
The second member function returns \tcode{addressof(r)}.

\pnum
\remarks
If \tcode{element_type} is \cv{}~\keyword{void}, the type of
\tcode{r} is unspecified; otherwise, it is \tcode{element_type\&}.
\end{itemdescr}

\rSec3[pointer.traits.optmem]{Optional members}

\pnum
Specializations of \tcode{pointer_traits} may define the member declared
in this subclause to customize the behavior of the standard library.
A specialization generated from the \tcode{pointer_traits} primary template
has no member by this name.

\indexlibrarymember{to_address}{pointer_traits}%
\begin{itemdecl}
static element_type* to_address(pointer p) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A pointer of type \tcode{element_type*} that references
the same location as the argument \tcode{p}.

\pnum
\begin{note}
This function is intended to be the inverse of \tcode{pointer_to}.
If defined, it customizes the behavior of
the non-member function
\tcode{to_address}\iref{pointer.conversion}.
\end{note}
\end{itemdescr}

\rSec2[pointer.conversion]{Pointer conversion}

\indexlibraryglobal{to_address}%
\begin{itemdecl}
template<class T> constexpr T* to_address(T* p) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{T} is not a function type.

\pnum
\returns
\tcode{p}.
\end{itemdescr}

\indexlibraryglobal{to_address}%
\begin{itemdecl}
template<class Ptr> constexpr auto to_address(const Ptr& p) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{pointer_traits<Ptr>::to_address(p)} if that expression is well-formed
(see \ref{pointer.traits.optmem}),
otherwise \tcode{to_address(p.operator->())}.
\end{itemdescr}

\rSec2[ptr.align]{Pointer alignment}

\indexlibraryglobal{align}%
\begin{itemdecl}
void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\begin{itemize}
\item
\tcode{alignment} is a power of two

\item
\tcode{ptr} represents the address of contiguous storage of at least
\tcode{space} bytes
\end{itemize}

\pnum
\effects
If it is possible to fit \tcode{size} bytes
of storage aligned by \tcode{alignment} into the buffer pointed to by
\tcode{ptr} with length \tcode{space}, the function updates
\tcode{ptr} to represent the first possible address of such storage
and decreases \tcode{space} by the number of bytes used for alignment.
Otherwise, the function does nothing.

\pnum
\returns
A null pointer if the requested aligned buffer
would not fit into the available space, otherwise the adjusted value
of \tcode{ptr}.

\pnum
\begin{note}
The function updates its \tcode{ptr}
and \tcode{space} arguments so that it can be called repeatedly
with possibly different \tcode{alignment} and \tcode{size}
arguments for the same buffer.
\end{note}
\end{itemdescr}

\indexlibraryglobal{assume_aligned}%
\begin{itemdecl}
template<size_t N, class T>
  constexpr T* assume_aligned(T* ptr);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{N} is a power of two.

\pnum
\expects
\tcode{ptr} points to an object $X$ of
a type similar\iref{conv.qual} to \tcode{T},
where $X$ has alignment \tcode{N}\iref{basic.align}.

\pnum
\returns
\tcode{ptr}.

\pnum
\throws
Nothing.

\pnum
\begin{note}
The alignment assumption on an object $X$
expressed by a call to \tcode{assume_aligned}
might 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 implementation 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 \tcode{assume_aligned}.
\end{note}
\end{itemdescr}

\indexlibraryglobal{is_sufficiently_aligned}%
\begin{itemdecl}
template<size_t Alignment, class T>
  bool is_sufficiently_aligned(T* ptr);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{Alignment} is a power of two.

\pnum
\expects
\tcode{p} points to
an object \tcode{X} of a type similar\iref{conv.qual} to \tcode{T}.

\pnum
\returns
\tcode{true} if \tcode{X} has alignment at least \tcode{Alignment},
otherwise \tcode{false}.

\pnum
\throws
Nothing.
\end{itemdescr}

\rSec2[obj.lifetime]{Explicit lifetime management}

\indexlibraryglobal{start_lifetime}%
\begin{itemdecl}
template<class T>
  constexpr void start_lifetime(T& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{T} is a complete type and
an implicit-lifetime\iref{basic.types} aggregate\iref{dcl.init.aggr}.

\pnum
\effects
If the object referenced by \tcode{r}
is already within its lifetime\iref{basic.life},
no effects.
Otherwise, begins the lifetime of the object referenced by \tcode{r}.
\begin{note}
No initialization is performed and no subobject has its lifetime started.
If \tcode{r} denotes a member of a union $U$,
it becomes the active member of $U$\iref{class.union}.
\end{note}
\end{itemdescr}

\indexlibraryglobal{start_lifetime_as}%
\begin{itemdecl}
template<class T>
  T* start_lifetime_as(void* p) noexcept;
template<class T>
  const T* start_lifetime_as(const void* p) noexcept;
template<class T>
  volatile T* start_lifetime_as(volatile void* p) noexcept;
template<class T>
  const volatile T* start_lifetime_as(const volatile void* p) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{T} is an implicit-lifetime type\iref{term.implicit.lifetime.type}
and not an incomplete type\iref{term.incomplete.type}.

\pnum
\expects
\range{p}{(char*)p + sizeof(T)} denotes a region of allocated storage
that is
a subset of the region of storage
reachable through\iref{basic.compound} \tcode{p} and
suitably aligned for the type \tcode{T}.

\pnum
\effects
Implicitly creates objects\iref{intro.object} within the denoted region
consisting of an object \placeholder{a} of type \tcode{T}
whose address is \tcode{p}, and
objects nested within \placeholder{a},
as follows:
The object representation of \placeholder{a}
is the contents of the storage prior to the call to \tcode{start_lifetime_as}.
The value of each created object \placeholder{o}
of trivially copyable type\iref{term.trivially.copyable.type} \tcode{U}
is determined in the same manner as for a call
to \tcode{bit_cast<U>(E)}\iref{bit.cast},
where \tcode{E} is an lvalue of type \tcode{U} denoting \placeholder{o},
except that the storage is not accessed.
The value of any other created object is unspecified.
\begin{note}
The unspecified value can be indeterminate.
\end{note}

\pnum
\returns
% FIXME: We should introduce "a" outside of the \effects clause
A pointer to the \placeholder{a} defined in the \Fundescx{Effects} paragraph.
\end{itemdescr}

\indexlibraryglobal{start_lifetime_as_array}%
\begin{itemdecl}
template<class T>
  T* start_lifetime_as_array(void* p, size_t n) noexcept;
template<class T>
  const T* start_lifetime_as_array(const void* p, size_t n) noexcept;
template<class T>
  volatile T* start_lifetime_as_array(volatile void* p, size_t n) noexcept;
template<class T>
  const volatile T* start_lifetime_as_array(const volatile void* p, size_t n) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{T} is a complete type.

\pnum
\expects
\tcode{p} is suitably aligned for an array of \tcode{T} or is null.
\tcode{n <= size_t(-1) / sizeof(T)} is \tcode{true}.
If \tcode{n > 0} is \tcode{true},
\range{(char*)p}{(char*)p + (n * sizeof(T))} denotes
a region of allocated storage that is
a subset of the region of storage
reachable through\iref{basic.compound} \tcode{p}.

\pnum
\effects
If \tcode{n > 0} is \tcode{true},
equivalent to
\tcode{start_lifetime_as<U>(p)}
where \tcode{U} is the type ``array of \tcode{n} \tcode{T}''.
Otherwise, there are no effects.

\pnum
\returns
A pointer to the first element of the created array,
if any;
otherwise,
a pointer that compares equal to \tcode{p}\iref{expr.eq}.
\end{itemdescr}

\rSec2[allocator.tag]{Allocator argument tag}

\indexlibraryglobal{allocator_arg_t}%
\indexlibraryglobal{allocator_arg}%
\begin{itemdecl}
namespace std {
  struct allocator_arg_t { explicit allocator_arg_t() = default; };
  inline constexpr allocator_arg_t allocator_arg{};
}
\end{itemdecl}

\pnum
The \tcode{allocator_arg_t} struct is an empty class type used as a unique type to
disambiguate constructor and function overloading. Specifically, several types (see
\tcode{tuple}~\ref{tuple}) have constructors with \tcode{allocator_arg_t} as the first
argument, immediately followed by an argument of a type that meets the
\oldconceptref{Allocator} requirements\iref{allocator.requirements.general}.

\rSec2[allocator.uses]{\tcode{uses_allocator}}

\rSec3[allocator.uses.trait]{\tcode{uses_allocator} trait}

\indexlibraryglobal{uses_allocator}%
\begin{itemdecl}
template<class T, class Alloc> struct uses_allocator;
\end{itemdecl}

\begin{itemdescr}
\pnum
\remarks
Automatically detects whether \tcode{T} has a nested \tcode{allocator_type} that
is convertible from \tcode{Alloc}. Meets the \oldconceptref{BinaryTypeTrait}
requirements\iref{meta.rqmts}. The implementation shall provide a definition that is
derived from \tcode{true_type} if the \grammarterm{qualified-id} \tcode{T::allocator_type}
is valid and denotes a type\iref{temp.deduct} and
\tcode{is_convertible_v<Alloc, T::allocator_type> != false}, otherwise it shall be
derived from \tcode{false_type}. A program may specialize this template to derive from
\tcode{true_type} for a program-defined type \tcode{T} that does not have a nested
\tcode{allocator_type} but nonetheless can be constructed with an allocator where
either:
\begin{itemize}
\item the first argument of a constructor has type \tcode{allocator_arg_t} and the
second argument has type \tcode{Alloc} or

\item the last argument of a constructor has type \tcode{Alloc}.
\end{itemize}
\end{itemdescr}

\rSec3[allocator.uses.construction]{Uses-allocator construction}

\pnum
\defnx{Uses-allocator construction}{uses-allocator construction}
with allocator \tcode{alloc} and constructor arguments \tcode{args...}
refers to the construction of an object of type \tcode{T}
such that \tcode{alloc} is passed to the constructor of \tcode{T}
if \tcode{T} uses an allocator type compatible with \tcode{alloc}.
When applied to the construction of an object of type \tcode{T},
it is equivalent to initializing it with the value of the expression
\tcode{make_obj_using_allocator<T>(alloc, args...)}, described below.

\pnum
The following utility functions support
three conventions for passing \tcode{alloc} to a constructor:
\begin{itemize}
\item
  If \tcode{T} does not use an allocator compatible with \tcode{alloc},
  then \tcode{alloc} is ignored.
\item
  Otherwise, if \tcode{T} has a constructor invocable as
  \tcode{T(allocator_arg_t\{\}, alloc, args...)} (leading-allocator convention),
  then uses-allocator construction chooses this constructor form.
\item
  Otherwise, if \tcode{T} has a constructor invocable as
  \tcode{T(args..., alloc)} (trailing-allocator convention),
  then uses-allocator construction chooses this constructor form.
\end{itemize}

\pnum
The \tcode{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 \tcode{pair}
such that uses-allocator construction is applied individually
to the \tcode{first} and \tcode{second} data members.
The \tcode{make_obj_using_allocator} and
\tcode{uninitialized_construct_using_allocator} function templates
apply the modified constructor arguments
to construct an object of type \tcode{T}
as a return value or in-place, respectively.
\begin{note}
For \tcode{uses_allocator_construction_args} and
\tcode{make_obj_using_allocator}, type \tcode{T}
is not deduced and must therefore be specified explicitly by the caller.
\end{note}

\indexlibraryglobal{uses_allocator_construction_args}%
\begin{itemdecl}
template<class T, class Alloc, class... Args>
  constexpr auto uses_allocator_construction_args(const Alloc& alloc,
                                                  Args&&... args) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{remove_cv_t<T>} is not a specialization of \tcode{pair}.

\pnum
\returns
A \tcode{tuple} value determined as follows:
\begin{itemize}
\item
  If \tcode{uses_allocator_v<remove_cv_t<T>, Alloc>} is \tcode{false} and
  \tcode{is_constructible_v<T, Args...>} is \tcode{true},
  return \tcode{forward_as_tuple(std::forward<Args>(args)...)}.
\item
  Otherwise, if \tcode{uses_allocator_v<remove_cv_t<T>, Alloc>} is \tcode{true} and
  \tcode{is_constructible_v<T, allocator_arg_t, const Alloc\&, Args...>}
  is \tcode{true},
  return
\begin{codeblock}
tuple<allocator_arg_t, const Alloc&, Args&&...>(
  allocator_arg, alloc, std::forward<Args>(args)...)
\end{codeblock}
\item
  Otherwise, if \tcode{uses_allocator_v<remove_cv_t<T>, Alloc>} is \tcode{true} and
  \tcode{is_constructible_v<T, Args..., const Alloc\&>} is \tcode{true},
  return \tcode{forward_as_tuple(std::forward<Args>(args)..., alloc)}.
\item
  Otherwise, the program is ill-formed.
\end{itemize}
\begin{note}
This definition prevents a silent failure
to pass the allocator to a constructor of a type for which
\tcode{uses_allocator_v<T, Alloc>} is \tcode{true}.
\end{note}
\end{itemdescr}

\indexlibraryglobal{uses_allocator_construction_args}%
\begin{itemdecl}
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;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{T1} be \tcode{T::first_type}.
Let \tcode{T2} be \tcode{T::second_type}.

\pnum
\constraints
\tcode{remove_cv_t<T>} is a specialization of \tcode{pair}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
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)));
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{uses_allocator_construction_args}%
\begin{itemdecl}
template<class T, class Alloc>
  constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{remove_cv_t<T>} is a specialization of \tcode{pair}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return uses_allocator_construction_args<T>(alloc, piecewise_construct,
                                           tuple<>{}, tuple<>{});
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{uses_allocator_construction_args}%
\begin{itemdecl}
template<class T, class Alloc, class U, class V>
  constexpr auto uses_allocator_construction_args(const Alloc& alloc,
                                                  U&& u, V&& v) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{remove_cv_t<T>} is a specialization of \tcode{pair}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return uses_allocator_construction_args<T>(alloc, piecewise_construct,
                                           forward_as_tuple(std::forward<U>(u)),
                                           forward_as_tuple(std::forward<V>(v)));
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{uses_allocator_construction_args}%
\begin{itemdecl}
template<class T, class Alloc, class U, class V>
  constexpr auto uses_allocator_construction_args(const Alloc& alloc,
                                                  pair<U, V>& pr) noexcept;
template<class T, class Alloc, class U, class V>
  constexpr auto uses_allocator_construction_args(const Alloc& alloc,
                                                  const pair<U, V>& pr) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{remove_cv_t<T>} is a specialization of \tcode{pair}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return uses_allocator_construction_args<T>(alloc, piecewise_construct,
                                           forward_as_tuple(pr.first),
                                           forward_as_tuple(pr.second));
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{uses_allocator_construction_args}%
\begin{itemdecl}
template<class T, class Alloc, class U, class V>
  constexpr auto uses_allocator_construction_args(const Alloc& alloc,
                                                  pair<U, V>&& pr) noexcept;
template<class T, class Alloc, class U, class V>
  constexpr auto uses_allocator_construction_args(const Alloc& alloc,
                                                  const pair<U, V>&& pr) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{remove_cv_t<T>} is a specialization of \tcode{pair}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return uses_allocator_construction_args<T>(alloc, piecewise_construct,
                                           forward_as_tuple(get<0>(std::move(pr))),
                                           forward_as_tuple(get<1>(std::move(pr))));
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{uses_allocator_construction_args}%
\begin{itemdecl}
template<class T, class Alloc, @\exposconcept{pair-like}@ P>
  constexpr auto uses_allocator_construction_args(const Alloc& alloc, P&& p) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{remove_cv_t<T>} is a specialization of \tcode{pair} and
\tcode{remove_cvref_t<P>} is not a specialization of \tcode{ranges::subrange}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return uses_allocator_construction_args<T>(alloc, piecewise_construct,
                                           forward_as_tuple(get<0>(std::forward<P>(p))),
                                           forward_as_tuple(get<1>(std::forward<P>(p))));
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{uses_allocator_construction_args}%
\begin{itemdecl}
template<class T, class Alloc, class U>
  constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \exposid{FUN} be the function template:
\begin{codeblock}
template<class A, class B>
  void @\exposid{FUN}@(const pair<A, B>&);
\end{codeblock}

\pnum
\constraints
\tcode{remove_cv_t<T>} is a specialization of \tcode{pair}, and either:
\begin{itemize}
\item
\tcode{remove_cvref_t<U>} is a specialization of \tcode{ranges::subrange}, or
\item
\tcode{U} does not satisfy \exposconcept{pair-like} and
the expression \tcode{\exposid{FUN}(u)} is not well-formed
when considered as an unevaluated operand.
\end{itemize}

\pnum
Let \exposid{pair-constructor} be an exposition-only class defined as follows:
\begin{codeblock}
class @\exposid{pair-constructor}@ {
  using @\exposid{pair-type}@ = remove_cv_t<T>;                             // \expos

  constexpr auto @\exposid{do-construct}@(const @\exposid{pair-type}@& p) const {       // \expos
    return make_obj_using_allocator<@\exposid{pair-type}@>(@\exposid{alloc_}@, p);
  }
  constexpr auto @\exposid{do-construct}@(@\exposid{pair-type}@&& p) const {            // \expos
    return make_obj_using_allocator<@\exposid{pair-type}@>(@\exposid{alloc_}@, std::move(p));
  }

  const Alloc& @\exposid{alloc_}@;  // \expos
  U& @\exposid{u_}@;                // \expos

public:
  constexpr operator @\exposid{pair-type}@() const {
    return @\exposid{do-construct}@(std::forward<U>(@\exposid{u_}@));
  }
};
\end{codeblock}

\pnum
\returns
\tcode{make_tuple(pc)},
where \tcode{pc} is a \exposid{pair-constructor} object
whose \exposid{alloc_} member is initialized with \tcode{alloc} and
whose \exposid{u_} member is initialized with \tcode{u}.
\end{itemdescr}

\indexlibraryglobal{make_obj_using_allocator}%
\begin{itemdecl}
template<class T, class Alloc, class... Args>
  constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return make_from_tuple<T>(uses_allocator_construction_args<T>(
                            alloc, std::forward<Args>(args)...));
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{uninitialized_construct_using_allocator}%
\begin{itemdecl}
template<class T, class Alloc, class... Args>
  constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return apply([&]<class... U>(U&&... xs) {
       return construct_at(p, std::forward<U>(xs)...);
     }, uses_allocator_construction_args<T>(alloc, std::forward<Args>(args)...));
\end{codeblock}
\end{itemdescr}

\rSec2[allocator.traits]{Allocator traits}

\rSec3[allocator.traits.general]{General}

\pnum
The class template \tcode{allocator_traits} supplies a uniform interface to all
allocator types.
An allocator cannot be a non-class type, however, even if \tcode{allocator_traits}
supplies the entire required interface.
\begin{note}
Thus, it is always possible to create
a derived class from an allocator.
\end{note}
If a program declares
an explicit or partial specialization of \tcode{allocator_traits},
the program is ill-formed, no diagnostic required.

\indexlibraryglobal{allocator_traits}%
\begin{codeblock}
namespace std {
  template<class Alloc> struct allocator_traits {
    using allocator_type     = Alloc;

    using value_type         = Alloc::value_type;

    using pointer            = @\seebelow@;
    using const_pointer      = @\seebelow@;
    using void_pointer       = @\seebelow@;
    using const_void_pointer = @\seebelow@;

    using difference_type    = @\seebelow@;
    using size_type          = @\seebelow@;

    using propagate_on_container_copy_assignment = @\seebelow@;
    using propagate_on_container_move_assignment = @\seebelow@;
    using propagate_on_container_swap            = @\seebelow@;
    using is_always_equal                        = @\seebelow@;

    template<class T> using rebind_alloc = @\seebelow@;
    template<class T> using rebind_traits = allocator_traits<rebind_alloc<T>>;

    static constexpr pointer allocate(Alloc& a, size_type n);
    static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint);
    static constexpr allocation_result<pointer, size_type>
      allocate_at_least(Alloc& a, size_type n);

    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);
  };
}
\end{codeblock}

\rSec3[allocator.traits.types]{Member types}

\indexlibrarymember{pointer}{allocator_traits}%
\begin{itemdecl}
using pointer = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Alloc::pointer} if
the \grammarterm{qualified-id} \tcode{Alloc::pointer} is valid and denotes a
type\iref{temp.deduct}; otherwise, \tcode{value_type*}.
\end{itemdescr}

\indexlibrarymember{const_pointer}{allocator_traits}%
\begin{itemdecl}
using const_pointer = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Alloc::const_pointer} if
the \grammarterm{qualified-id} \tcode{Alloc::const_pointer} is valid and denotes a
type\iref{temp.deduct}; otherwise,
\tcode{pointer_traits<pointer>::rebind<\brk{}const value_type>}.
\end{itemdescr}

\indexlibrarymember{void_pointer}{allocator_traits}%
\begin{itemdecl}
using void_pointer = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Alloc::void_pointer} if
the \grammarterm{qualified-id} \tcode{Alloc::void_pointer} is valid and denotes a
type\iref{temp.deduct}; otherwise,
\tcode{pointer_traits<pointer>::rebind<\brk{}void>}.
\end{itemdescr}

\indexlibrarymember{const_void_pointer}{allocator_traits}%
\begin{itemdecl}
using const_void_pointer = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Alloc::const_void_pointer} if
the \grammarterm{qualified-id} \tcode{Alloc::const_void_pointer} is valid and denotes a
type\iref{temp.deduct}; otherwise,
\tcode{pointer_traits<pointer>::\brk{}rebind<const void>}.
\end{itemdescr}

\indexlibrarymember{difference_type}{allocator_traits}%
\begin{itemdecl}
using difference_type = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Alloc::difference_type} if
the \grammarterm{qualified-id} \tcode{Alloc::difference_type} is valid and denotes a
type\iref{temp.deduct}; otherwise,
\tcode{pointer_traits<pointer>::dif\-ference_type}.
\end{itemdescr}

\indexlibrarymember{size_type}{allocator_traits}%
\begin{itemdecl}
using size_type = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Alloc::size_type} if
the \grammarterm{qualified-id} \tcode{Alloc::size_type} is valid and denotes a
type\iref{temp.deduct}; otherwise,
\tcode{make_unsigned_t<difference_type>}.
\end{itemdescr}

\indexlibrarymember{propagate_on_container_copy_assignment}{allocator_traits}%
\begin{itemdecl}
using propagate_on_container_copy_assignment = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Alloc::propagate_on_container_copy_assignment} if
the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_copy_assignment} is valid and denotes a
type\iref{temp.deduct}; otherwise
\tcode{false_type}.
\end{itemdescr}

\indexlibrarymember{propagate_on_container_move_assignment}{allocator_traits}%
\begin{itemdecl}
using propagate_on_container_move_assignment = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Alloc::propagate_on_container_move_assignment} if
the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_move_assignment} is valid and denotes a
type\iref{temp.deduct}; otherwise
\tcode{false_type}.
\end{itemdescr}

\indexlibrarymember{propagate_on_container_swap}{allocator_traits}%
\begin{itemdecl}
using propagate_on_container_swap = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Alloc::propagate_on_container_swap} if
the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_swap} is valid and denotes a
type\iref{temp.deduct}; otherwise
\tcode{false_type}.
\end{itemdescr}

\indexlibrarymember{is_always_equal}{allocator_traits}%
\begin{itemdecl}
using is_always_equal = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{Alloc::is_always_equal} if
the \grammarterm{qualified-id} \tcode{Alloc::is_always_equal}
is valid and denotes a type\iref{temp.deduct};
otherwise \tcode{is_empty<Alloc>::type}.
\end{itemdescr}

\indexlibrarymember{rebind_alloc}{allocator_traits}%
\begin{itemdecl}
template<class T> using rebind_alloc = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\templalias \tcode{Alloc::rebind<T>::other} if
the \grammarterm{qualified-id} \tcode{Alloc::rebind<T>::other} is valid and denotes a
type\iref{temp.deduct}; otherwise,
\tcode{Alloc<T, Args>} if \tcode{Alloc} is a class template specialization
of the form \tcode{Alloc<U, Args>}, where \tcode{Args} is zero or more type arguments;
otherwise, the instantiation of \tcode{rebind_alloc} is ill-formed.
\end{itemdescr}

\rSec3[allocator.traits.members]{Static member functions}

\indexlibrarymember{allocate}{allocator_traits}%
\begin{itemdecl}
static constexpr pointer allocate(Alloc& a, size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{a.allocate(n)}.
\end{itemdescr}

\indexlibrarymember{allocate}{allocator_traits}%
\begin{itemdecl}
static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{a.allocate(n, hint)} if that expression is well-formed; otherwise, \tcode{a.allocate(n)}.
\end{itemdescr}

\indexlibrarymember{allocate_at_least}{allocator_traits}%
\begin{itemdecl}
static constexpr allocation_result<pointer, size_type> allocate_at_least(Alloc& a, size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{a.allocate_at_least(n)} if that expression is well-formed;
otherwise, \tcode{\{a.allocate(n), n\}}.
\end{itemdescr}

\indexlibrarymember{deallocate}{allocator_traits}%
\begin{itemdecl}
static constexpr void deallocate(Alloc& a, pointer p, size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Calls \tcode{a.deallocate(p, n)}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{construct}{allocator_traits}%
\begin{itemdecl}
template<class T, class... Args>
  static constexpr void construct(Alloc& a, T* p, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Calls \tcode{a.construct(p, std::forward<Args>(args)...)}
if that call is well-formed;
otherwise, invokes \tcode{construct_at(p, std::forward<Args>(args)...)}.
\end{itemdescr}

\indexlibrarymember{destroy}{allocator_traits}%
\begin{itemdecl}
template<class T>
  static constexpr void destroy(Alloc& a, T* p);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Calls \tcode{a.destroy(p)} if that call is well-formed; otherwise, invokes
\tcode{destroy_at(p)}.
\end{itemdescr}

\indexlibrarymember{max_size}{allocator_traits}%
\begin{itemdecl}
static constexpr size_type max_size(const Alloc& a) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{a.max_size()} if that expression is well-formed; otherwise,
\tcode{numeric_limits<size_type>::\brk{}max() / sizeof(value_type)}.
\end{itemdescr}

\indexlibrarymember{select_on_container_copy_construction}{allocator_traits}%
\begin{itemdecl}
static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{rhs.select_on_container_copy_construction()} if that expression is
well-formed; otherwise, \tcode{rhs}.
\end{itemdescr}

\rSec3[allocator.traits.other]{Other}

\pnum
The class template \tcode{allocation_result} has
the template parameters, data members, and special members specified above.
It has no base classes or members other than those specified.

\rSec2[default.allocator]{The default allocator}

\rSec3[default.allocator.general]{General}

\pnum
All specializations of the default allocator meet the
allocator completeness requirements\iref{allocator.requirements.completeness}.

\indexlibraryglobal{allocator}%
\indexlibrarymember{value_type}{allocator}%
\indexlibrarymember{size_type}{allocator}%
\indexlibrarymember{difference_type}{allocator}%
\indexlibrarymember{propagate_on_container_move_assignment}{allocator}%
\indexlibrarymember{operator=}{allocator}%
\begin{codeblock}
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;

    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;

    constexpr T* allocate(size_t n);
    constexpr allocation_result<T*> allocate_at_least(size_t n);
    constexpr void deallocate(T* p, size_t n);
  };
}
\end{codeblock}

\pnum
\tcode{allocator_traits<allocator<T>>::is_always_equal::value}
is \tcode{true} for any \tcode{T}.

\rSec3[allocator.members]{Members}

\pnum
Except for the destructor, member functions of the default allocator shall not introduce
data races\iref{intro.multithread} 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.

\indexlibrarymember{allocate}{allocator}%
\begin{itemdecl}
constexpr T* allocate(size_t n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{T} is not an incomplete type\iref{term.incomplete.type}.

\pnum
\returns
A pointer to the initial element of an array of \tcode{n} \tcode{T}.

\pnum
\throws
\tcode{bad_array_new_length} if
\tcode{numeric_limits<size_t>::max() / sizeof(T) < n}, or
\tcode{bad_alloc} if the storage cannot be obtained.

\pnum
\remarks
The storage for the array
is obtained by calling \tcode{::operator new}\iref{new.delete},
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.
\end{itemdescr}

\indexlibrarymember{allocate_at_least}{allocator}%
\begin{itemdecl}
constexpr allocation_result<T*> allocate_at_least(size_t n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{T} is not an incomplete type\iref{term.incomplete.type}.

\pnum
\returns
\tcode{allocation_result<T*>\{ptr, count\}},
where \tcode{ptr} is a pointer to
the initial element of an array of \tcode{count} \tcode{T} and
$\tcode{count} \geq \tcode{n}$.

\pnum
\throws
\tcode{bad_array_new_length}
if $\tcode{numeric_limits<size_t>::max() / sizeof(T)} < \tcode{n}$,
or \tcode{bad_alloc} if the storage cannot be obtained.

\pnum
\remarks
The storage for the array is obtained by calling \tcode{::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.
\end{itemdescr}

\indexlibrarymember{deallocate}{allocator}%
\begin{itemdecl}
constexpr void deallocate(T* p, size_t n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\begin{itemize}
\item
If \tcode{p} is memory that was obtained by a call to \tcode{allocate_at_least},
let \tcode{ret} be the value returned and
\tcode{req} be the value passed as the first argument to that call.
\tcode{p} is equal to \tcode{ret.ptr} and
\tcode{n} is a value such that $\tcode{req} \leq \tcode{n} \leq \tcode{ret.count}$.
\item
Otherwise, \tcode{p} is a pointer value obtained from \tcode{allocate}.
\tcode{n} equals the value passed as the first argument
to the invocation of \tcode{allocate} which returned \tcode{p}.
\end{itemize}

\pnum
\effects
Deallocates the storage referenced by \tcode{p}.

\pnum
\remarks
Uses
\tcode{::operator delete}\iref{new.delete},
but it is unspecified
when this function is called.
\end{itemdescr}

\rSec3[allocator.globals]{Operators}

\indexlibrarymember{operator==}{allocator}%
\begin{itemdecl}
template<class T, class U>
  constexpr bool operator==(const allocator<T>&, const allocator<U>&) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true}.
\end{itemdescr}

\rSec2[specialized.addressof]{\tcode{addressof}}

\indexlibraryglobal{addressof}%
\begin{itemdecl}
template<class T> constexpr T* addressof(T& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The actual address of the object or function referenced by \tcode{r}, even in the
presence of an overloaded \tcode{operator\&}.

\pnum
\remarks
An expression \tcode{addressof(E)}
is a constant subexpression\iref{defns.const.subexpr}
if \tcode{E} is an lvalue constant subexpression.
\end{itemdescr}

\rSec2[c.malloc]{C library memory allocation}

\pnum
\begin{note}
The header \libheaderref{cstdlib}
declares the functions described in this subclause.
\end{note}

\indexlibraryglobal{aligned_alloc}%
\indexlibraryglobal{calloc}%
\indexlibraryglobal{malloc}%
\begin{itemdecl}
void* aligned_alloc(size_t alignment, size_t size);
void* calloc(size_t nmemb, size_t size);
void* malloc(size_t size);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions have the semantics specified in the C standard library.

\pnum
\remarks
These functions do not attempt to allocate
storage by calling \tcode{::operator new()}\iref{new.delete}.
\indexlibrarymember{new}{operator}%

\pnum
These functions implicitly create objects\iref{intro.object}
in the returned region of storage and
return a pointer to a suitable created object.
In the case of \tcode{calloc},
the objects are created before the storage is zeroed.
\end{itemdescr}

\indexlibraryglobal{realloc}%
\begin{itemdecl}
void* realloc(void* ptr, size_t size);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{free(ptr)} has well-defined behavior.

\pnum
\effects
If \tcode{ptr} is not null and \tcode{size} is zero,
the behavior is erroneous and the effects are implementation-defined.
Otherwise, this function has the semantics specified in the C standard library.

\pnum
\remarks
This function does not attempt to allocate storage
by calling \tcode{::operator new()}\iref{new.delete}.
When a non-null pointer is returned,
this function implicitly creates objects\iref{intro.object}
in the returned region of storage and
returns a pointer to a suitable created object.
The objects are created before the storage is copied.
\end{itemdescr}

\indexlibraryglobal{free}%
\begin{itemdecl}
void free(void* ptr);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
This function has the semantics specified in the C standard library.

\pnum
\remarks
This function does not attempt to
deallocate storage by calling
\tcode{::operator delete()}\indexlibrarymember{delete}{operator}.
\end{itemdescr}

\xrefc{7.24.4}

\rSec1[smartptr]{Smart pointers}

\rSec2[unique.ptr]{Unique-ownership pointers}

\rSec3[unique.ptr.general]{General}

\pnum
A \defn{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 \textit{u} that stores a pointer to a second object \textit{p} and
will dispose of \textit{p} when \textit{u} is itself destroyed (e.g., when
leaving block scope\iref{stmt.dcl}). In this context, \textit{u} is said
to \defn{own} \tcode{p}.

\pnum
The mechanism by which \textit{u} disposes of \textit{p} is known as
\textit{p}'s associated \defn{deleter}, a function object whose correct
invocation results in \textit{p}'s appropriate disposition (typically its deletion).

\pnum
Let the notation \textit{u.p} denote the pointer stored by \textit{u}, and
let \textit{u.d} denote the associated deleter. Upon request, \textit{u} can
\defn{reset} (replace) \textit{u.p} and \textit{u.d} with another pointer and
deleter, but properly disposes of its owned object via the associated
deleter before such replacement is considered completed.

\pnum
Each object of a type \tcode{U} instantiated from the \tcode{unique_ptr} template
specified in \ref{unique.ptr} has the strict ownership semantics, specified above,
of a unique pointer. In partial satisfaction of these semantics, each such \tcode{U}
is \oldconceptref{MoveConstructible} and \oldconceptref{MoveAssignable}, but is not
\oldconceptref{CopyConstructible} nor \oldconceptref{CopyAssignable}.
The template parameter \tcode{T} of \tcode{unique_ptr} may be an incomplete type.

\pnum
\begin{note}
The uses
of \tcode{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}

\rSec3[unique.ptr.dltr]{Default deleters}

\rSec4[unique.ptr.dltr.general]{General}

\pnum
The class template \tcode{default_delete} serves as the default deleter (destruction policy)
for the class template \tcode{unique_ptr}.

\pnum
The template parameter \tcode{T} of \tcode{default_delete} may be
an incomplete type.

\rSec4[unique.ptr.dltr.dflt]{\tcode{default_delete}}

\begin{codeblock}
namespace std {
  template<class T> struct default_delete {
    constexpr default_delete() noexcept = default;
    template<class U> constexpr default_delete(const default_delete<U>&) noexcept;
    constexpr void operator()(T*) const;
  };
}
\end{codeblock}

\indexlibraryctor{default_delete}%
\begin{itemdecl}
template<class U> constexpr default_delete(const default_delete<U>& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{U*} is implicitly convertible to \tcode{T*}.

\pnum
\effects
Constructs a \tcode{default_delete} object
from another \tcode{default_delete<U>} object.
\end{itemdescr}

\indexlibrarymember{operator()}{default_delete}%
\begin{itemdecl}
constexpr void operator()(T* ptr) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{T} is a complete type.

\pnum
\effects
Calls \keyword{delete} on \tcode{ptr}.
\end{itemdescr}

\rSec4[unique.ptr.dltr.dflt1]{\tcode{default_delete<T[]>}}

\begin{codeblock}
namespace std {
  template<class T> struct default_delete<T[]> {
    constexpr default_delete() noexcept = default;
    template<class U> constexpr default_delete(const default_delete<U[]>&) noexcept;
    template<class U> constexpr void operator()(U* ptr) const;
  };
}
\end{codeblock}

\indexlibraryctor{default_delete}
\begin{itemdecl}
template<class U> constexpr default_delete(const default_delete<U[]>& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{U(*)[]} is convertible to \tcode{T(*)[]}.

\pnum
\effects
Constructs a \tcode{default_delete} object from another \tcode{default_delete<U[]>} object.
\end{itemdescr}

\indexlibrarymember{operator()}{default_delete}%
\begin{itemdecl}
template<class U> constexpr void operator()(U* ptr) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{U(*)[]} is convertible to \tcode{T(*)[]}.

\pnum
\mandates
\tcode{U} is a complete type.

\pnum
\effects
Calls \tcode{delete[]} on \tcode{ptr}.
\end{itemdescr}

\rSec3[unique.ptr.single]{\tcode{unique_ptr} for single objects}

\rSec4[unique.ptr.single.general]{General}

\indexlibraryglobal{unique_ptr}%
\begin{codeblock}
namespace std {
  template<class T, class D = default_delete<T>> class unique_ptr {
  public:
    using pointer      = @\seebelow@;
    using element_type = T;
    using deleter_type = D;

    // \ref{unique.ptr.single.ctor}, constructors
    constexpr unique_ptr() noexcept;
    constexpr explicit unique_ptr(type_identity_t<pointer> p) noexcept;
    constexpr unique_ptr(type_identity_t<pointer> p, @\seebelow@ d1) noexcept;
    constexpr unique_ptr(type_identity_t<pointer> p, @\seebelow@ d2) noexcept;
    constexpr unique_ptr(unique_ptr&& u) noexcept;
    constexpr unique_ptr(nullptr_t) noexcept;
    template<class U, class E>
      constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;

    // \ref{unique.ptr.single.dtor}, destructor
    constexpr ~unique_ptr();

    // \ref{unique.ptr.single.asgn}, assignment
    constexpr unique_ptr& operator=(unique_ptr&& u) noexcept;
    template<class U, class E>
      constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
    constexpr unique_ptr& operator=(nullptr_t) noexcept;

    // \ref{unique.ptr.single.observers}, observers
    constexpr add_lvalue_reference_t<T> operator*() const noexcept(@\seebelow@);
    constexpr pointer operator->() const noexcept;
    constexpr pointer get() const noexcept;
    constexpr deleter_type& get_deleter() noexcept;
    constexpr const deleter_type& get_deleter() const noexcept;
    constexpr explicit operator bool() const noexcept;

    // \ref{unique.ptr.single.modifiers}, modifiers
    constexpr pointer release() noexcept;
    constexpr void reset(pointer p = pointer()) noexcept;
    constexpr void swap(unique_ptr& u) noexcept;

    // disable copy from lvalue
    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;
  };
}
\end{codeblock}

\pnum
A program that instantiates the definition of \tcode{unique_ptr<T, D>}
is ill-formed if \tcode{T*} is an invalid type.
\begin{note}
This prevents the instantiation of specializations such as
\tcode{unique_ptr<T\&, D>} and \tcode{unique_ptr<int() const, D>}.
\end{note}

\pnum
The default type for the template parameter \tcode{D} is
\tcode{default_delete}. A client-supplied template argument
\tcode{D} shall be a function
object type\iref{function.objects}, lvalue reference to function, or
lvalue reference to function object type
for which, given
a value \tcode{d} of type \tcode{D} and a value
\tcode{ptr} of type \tcode{unique_ptr<T, D>::pointer}, the expression
\tcode{d(ptr)} is valid and has the effect of disposing of the
pointer as appropriate for that deleter.

\pnum
If the deleter's type \tcode{D} is not a reference type, \tcode{D} shall meet
the \oldconceptref{Destructible} requirements (\tref{cpp17.destructible}).

\pnum
If the \grammarterm{qualified-id} \tcode{remove_reference_t<D>::pointer} is valid and denotes a
type\iref{temp.deduct}, then \tcode{unique_ptr<T,
D>::pointer} shall be a synonym for \tcode{remove_reference_t<D>::pointer}. Otherwise
\tcode{unique_ptr<T, D>::pointer} shall be a synonym for \tcode{element_type*}. The type \tcode{unique_ptr<T,
D>::pointer} shall
meet the \oldconceptref{NullablePointer} requirements (\tref{cpp17.nullablepointer}).

\pnum
\begin{example}
Given an allocator type \tcode{X}\iref{allocator.requirements.general} and
letting \tcode{A} be a synonym for \tcode{allocator_traits<X>}, the types \tcode{A::pointer},
\tcode{A::const_pointer}, \tcode{A::void_pointer}, and \tcode{A::const_void_pointer}
may be used as \tcode{unique_ptr<T, D>::pointer}.
\end{example}

\rSec4[unique.ptr.single.ctor]{Constructors}

\indexlibraryctor{unique_ptr}%
\begin{itemdecl}
constexpr unique_ptr() noexcept;
constexpr unique_ptr(nullptr_t) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_pointer_v<deleter_type>} is \tcode{false} and
\tcode{is_default_constructible_v<deleter_type>} is \tcode{true}.

\pnum
\expects
\tcode{D} meets the \oldconceptref{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}),
and that construction does not throw an exception.

\pnum
\effects
Constructs a \tcode{unique_ptr} object that owns
nothing, value-initializing the stored pointer and the stored deleter.

\pnum
\ensures
\tcode{get() == nullptr}. \tcode{get_deleter()}
returns a reference to the stored deleter.
\end{itemdescr}

\indexlibraryctor{unique_ptr}%
\begin{itemdecl}
constexpr explicit unique_ptr(type_identity_t<pointer> p) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_pointer_v<deleter_type>} is \tcode{false} and
\tcode{is_default_constructible_v<deleter_type>} is \tcode{true}.

\pnum
\expects
\tcode{D} meets the \oldconceptref{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}),
and that construction does not throw an exception.

\pnum
\effects
Constructs a \tcode{unique_ptr} which owns
\tcode{p}, initializing the stored pointer with \tcode{p} and
value-initializing the stored deleter.

\pnum
\ensures
\tcode{get() == p}. \tcode{get_deleter()}
returns a reference to the stored deleter.
\end{itemdescr}

\indexlibraryctor{unique_ptr}%
\begin{itemdecl}
constexpr unique_ptr(type_identity_t<pointer> p, const D& d) noexcept;
constexpr unique_ptr(type_identity_t<pointer> p, remove_reference_t<D>&& d) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<D, decltype(d)>} is \tcode{true}.

\pnum
\expects
For the first constructor, if \tcode{D} is not a reference type,
\tcode{D} meets the \oldconceptref{CopyConstructible} requirements and
such construction does not exit via an exception.
For the second constructor, if \tcode{D} is not a reference type,
\tcode{D} meets the \oldconceptref{MoveConstructible} requirements and
such construction does not exit via an exception.

\pnum
\effects
Constructs a \tcode{unique_ptr} object which owns \tcode{p}, initializing
the stored pointer with \tcode{p} and initializing the deleter
from \tcode{std::forward<decltype(d)>(d)}.

\pnum
\ensures
\tcode{get() == p}.
\tcode{get_deleter()} returns a reference to the stored
deleter. If \tcode{D} is a reference type then \tcode{get_deleter()}
returns a reference to the lvalue \tcode{d}.

\pnum
\remarks
If \tcode{D} is a reference type,
the second constructor is defined as deleted.

\pnum
\begin{example}
\begin{codeblock}
D d;
unique_ptr<int, D> p1(new int, D());        // \tcode{D} must be \oldconceptref{MoveConstructible}
unique_ptr<int, D> p2(new int, d);          // \tcode{D} must be \oldconceptref{CopyConstructible}
unique_ptr<int, D&> p3(new int, d);         // \tcode{p3} holds a reference to \tcode{d}
unique_ptr<int, const D&> p4(new int, D()); // error: rvalue deleter object combined
                                            // with reference deleter type
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibraryctor{unique_ptr}%
\begin{itemdecl}
constexpr unique_ptr(unique_ptr&& u) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_move_constructible_v<D>} is \tcode{true}.

\pnum
\expects
If \tcode{D} is not a reference type,
\tcode{D} meets the \oldconceptref{MoveConstructible}
requirements (\tref{cpp17.moveconstructible}).
Construction
of the deleter from an rvalue of type \tcode{D} does not
throw an exception.

\pnum
\effects
Constructs a \tcode{unique_ptr} from
\tcode{u}. If \tcode{D} is a reference type, this
deleter is copy constructed from \tcode{u}'s deleter; otherwise, this
deleter is move constructed from \tcode{u}'s deleter.
\begin{note}
The
construction of the deleter can be implemented with \tcode{std::forward<D>}.
\end{note}

\pnum
\ensures
\tcode{get()} yields the value \tcode{u.get()}
yielded before the construction. \tcode{u.get() == nullptr}.
\tcode{get_deleter()} returns a reference
to the stored deleter that was constructed from
\tcode{u.get_deleter()}. If \tcode{D} is a reference type then
\tcode{get_deleter()} and \tcode{u.get_deleter()} both reference
the same lvalue deleter.
\end{itemdescr}

\indexlibraryctor{unique_ptr}%
\begin{itemdecl}
template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item \tcode{unique_ptr<U, E>::pointer} is implicitly convertible to \tcode{pointer},
\item \tcode{U} is not an array type, and
\item either \tcode{D} is a reference type and \tcode{E} is the same type as \tcode{D}, or
\tcode{D} is not a reference type and \tcode{E} is implicitly convertible to \tcode{D}.
\end{itemize}

\pnum
\expects
If \tcode{E} is not a reference type,
construction of the deleter from an rvalue of type \tcode{E}
is well-formed and does not throw an exception.
Otherwise, \tcode{E} is a reference type and
construction of the deleter from an lvalue of type \tcode{E}
is well-formed and does not throw an exception.

\pnum
\effects
Constructs a \tcode{unique_ptr} from \tcode{u}.
If \tcode{E} is a reference type, this deleter is copy constructed from
\tcode{u}'s deleter; otherwise, this deleter is move constructed from \tcode{u}'s
deleter.
\begin{note}
The deleter constructor can be implemented with
\tcode{std::forward<E>}.
\end{note}

\pnum
\ensures
\tcode{get()} yields the value \tcode{u.get()}
yielded before the construction. \tcode{u.get() == nullptr}.
\tcode{get_deleter()} returns a reference
to the stored deleter that was constructed from
\tcode{u.get_deleter()}.
\end{itemdescr}

\rSec4[unique.ptr.single.dtor]{Destructor}

\indexlibrarydtor{unique_ptr}%
\begin{itemdecl}
constexpr ~unique_ptr();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{if (get()) get_deleter()(get());}
\begin{note}
The use of \tcode{default_delete} requires \tcode{T} to be a complete type.
\end{note}

\pnum
\remarks
The behavior is undefined
if the evaluation of \tcode{get_deleter()(get())} throws an exception.
\end{itemdescr}

\rSec4[unique.ptr.single.asgn]{Assignment}

\indexlibrarymember{operator=}{unique_ptr}%
\begin{itemdecl}
constexpr unique_ptr& operator=(unique_ptr&& u) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_move_assignable_v<D>} is \tcode{true}.

\pnum
\expects
If \tcode{D} is not a reference type, \tcode{D} meets the
\oldconceptref{MoveAssignable} requirements (\tref{cpp17.moveassignable}) and assignment
of the deleter from an rvalue of type \tcode{D} does not throw an exception.
Otherwise, \tcode{D} is a reference type;
\tcode{remove_reference_t<D>} meets the \oldconceptref{CopyAssignable}
requirements and assignment of the deleter from an
lvalue of type \tcode{D} does not throw an exception.

\pnum
\effects
Calls \tcode{reset(u.release())} followed by
\tcode{get_deleter() = std::forward<D>(u.get_dele\-ter())}.

\pnum
\ensures
If \tcode{this != addressof(u)},
\tcode{u.get() == nullptr},
otherwise \tcode{u.get()} is unchanged.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator=}{unique_ptr}%
\begin{itemdecl}
template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item \tcode{unique_ptr<U, E>::pointer} is implicitly convertible to \tcode{pointer}, and
\item \tcode{U} is not an array type, and
\item \tcode{is_assignable_v<D\&, E\&\&>} is \tcode{true}.
\end{itemize}

\pnum
\expects
If \tcode{E} is not a reference type,
assignment of the deleter from an rvalue of type \tcode{E}
is well-formed and does not throw an exception.
Otherwise, \tcode{E} is a reference type and
assignment of the deleter from an lvalue of type \tcode{E}
is well-formed and does not throw an exception.

\pnum
\effects
Calls \tcode{reset(u.release())} followed by
\tcode{get_deleter() = std::forward<E>(u.get_dele\-ter())}.

\pnum
\ensures
\tcode{u.get() == nullptr}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator=}{unique_ptr}%
\begin{itemdecl}
constexpr unique_ptr& operator=(nullptr_t) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
As if by \tcode{reset()}.

\pnum
\ensures
\tcode{get() == nullptr}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\rSec4[unique.ptr.single.observers]{Observers}

\indexlibrarymember{operator*}{unique_ptr}%
\begin{itemdecl}
constexpr add_lvalue_reference_t<T> operator*() const noexcept(noexcept(*declval<pointer>()));
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{*declval<pointer>()} is a well-formed expression.

\pnum
\mandates
\tcode{reference_converts_from_temporary_v<add_lvalue_reference_t<T>, decltype(\linebreak{}*declval<pointer>())>} is \tcode{false}.

\pnum
\expects
\tcode{get() != nullptr} is \tcode{true}.

\pnum
\returns
\tcode{*get()}.

\end{itemdescr}

\indexlibrarymember{operator->}{unique_ptr}%
\begin{itemdecl}
constexpr pointer operator->() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{get() != nullptr}.

\pnum
\returns
\tcode{get()}.

\pnum
\begin{note}
The use of this function typically requires that \tcode{T} be a complete type.
\end{note}
\end{itemdescr}

\indexlibrarymember{get}{unique_ptr}%
\begin{itemdecl}
constexpr pointer get() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The stored pointer.
\end{itemdescr}

\indexlibrarymember{get_deleter}{unique_ptr}%
\begin{itemdecl}
constexpr deleter_type& get_deleter() noexcept;
constexpr const deleter_type& get_deleter() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A reference to the stored deleter.
\end{itemdescr}

\indexlibrarymember{operator bool}{unique_ptr}%
\begin{itemdecl}
constexpr explicit operator bool() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{get() != nullptr}.
\end{itemdescr}

\rSec4[unique.ptr.single.modifiers]{Modifiers}

\indexlibrarymember{release}{unique_ptr}%
\begin{itemdecl}
constexpr pointer release() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{get() == nullptr}.

\pnum
\returns
The value \tcode{get()} had at the start of
the call to \tcode{release}.
\end{itemdescr}

\indexlibrarymember{reset}{unique_ptr}%
\begin{itemdecl}
constexpr void reset(pointer p = pointer()) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Assigns \tcode{p} to the stored pointer, and then,
with the old value of the stored pointer, \tcode{old_p},
evaluates \tcode{if (old_p) get_deleter()(old_p);}
\begin{note}
The order of these operations is significant
because the call to \tcode{get_deleter()} might destroy \tcode{*this}.
\end{note}

\pnum
\ensures
\tcode{get() == p}.
\begin{note}
The postcondition does not hold if the call to \tcode{get_deleter()}
destroys \tcode{*this} since \tcode{this->get()} is no longer a valid expression.
\end{note}

\pnum
\remarks
The behavior is undefined
if the evaluation of \tcode{get_deleter()(old_p)} throws an exception.
\end{itemdescr}

\indexlibrarymember{swap}{unique_ptr}%
\begin{itemdecl}
constexpr void swap(unique_ptr& u) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{get_deleter()} is swappable\iref{swappable.requirements} and
does not throw an exception under \tcode{swap}.

\pnum
\effects
Invokes \tcode{swap} on the stored pointers and on the stored
deleters of \tcode{*this} and \tcode{u}.
\end{itemdescr}

\rSec3[unique.ptr.runtime]{\tcode{unique_ptr} for array objects with a runtime length}

\rSec4[unique.ptr.runtime.general]{General}

\indexlibraryglobal{unique_ptr}%
\begin{codeblock}
namespace std {
  template<class T, class D> class unique_ptr<T[], D> {
  public:
    using pointer      = @\seebelow@;
    using element_type = T;
    using deleter_type = D;

    // \ref{unique.ptr.runtime.ctor}, constructors
    constexpr unique_ptr() noexcept;
    template<class U> constexpr explicit unique_ptr(U p) noexcept;
    template<class U> constexpr unique_ptr(U p, @\seebelow@ d) noexcept;
    template<class U> constexpr unique_ptr(U p, @\seebelow@ d) noexcept;
    constexpr unique_ptr(unique_ptr&& u) noexcept;
    template<class U, class E>
      constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;
    constexpr unique_ptr(nullptr_t) noexcept;

    // destructor
    constexpr ~unique_ptr();

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

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

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

    // disable copy from lvalue
    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;
  };
}
\end{codeblock}

\pnum
A specialization for array types is provided with a slightly altered
interface.

\begin{itemize}
\item Conversions between different types of
\tcode{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
\tcode{unique_ptr}, produce an ill-formed program.

\item Pointers to types derived from \tcode{T} are
rejected by the constructors, and by \tcode{reset}.

\item The observers \tcode{operator*} and
\tcode{operator->} are not provided.

\item The indexing observer \tcode{operator[]} is provided.

\item The default deleter will call \tcode{delete[]}.
\end{itemize}

\pnum
Descriptions are provided below only for members that
differ from the primary template.

\pnum
The template argument \tcode{T} shall be a complete type.

\rSec4[unique.ptr.runtime.ctor]{Constructors}

\indexlibraryctor{unique_ptr}%
\begin{itemdecl}
template<class U> constexpr explicit unique_ptr(U p) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
This constructor behaves the same as
the constructor in the primary template that
takes a single parameter of type \tcode{pointer}.

\pnum
\constraints
\begin{itemize}
\item \tcode{U} is the same type as \tcode{pointer}, or
\item \tcode{pointer} is the same type as \tcode{element_type*},
\tcode{U} is a pointer type \tcode{V*}, and
\tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}.
\end{itemize}
\end{itemdescr}

\indexlibraryctor{unique_ptr}%
\begin{itemdecl}
template<class U> constexpr unique_ptr(U p, @\seebelow@ d) noexcept;
template<class U> constexpr unique_ptr(U p, @\seebelow@ d) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
These constructors behave the same as
the constructors in the primary template that
take a parameter of type \tcode{pointer} and a second parameter.

\pnum
\constraints
\begin{itemize}
\item \tcode{U} is the same type as \tcode{pointer},
\item \tcode{U} is \tcode{nullptr_t}, or
\item \tcode{pointer} is the same type as \tcode{element_type*},
      \tcode{U} is a pointer type \tcode{V*}, and
      \tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}.
\end{itemize}
\end{itemdescr}

\indexlibraryctor{unique_ptr}%
\begin{itemdecl}
template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
This constructor behaves the same as in the primary template.

\pnum
\constraints
Where \tcode{UP} is \tcode{unique_ptr<U, E>}:
\begin{itemize}
\item \tcode{U} is an array type, and
\item \tcode{pointer} is the same type as \tcode{element_type*}, and
\item \tcode{UP::pointer} is the same type as \tcode{UP::element_type*}, and
\item \tcode{UP::element_type(*)[]} is convertible to \tcode{element_type(*)[]}, and
\item either \tcode{D} is a reference type and \tcode{E} is the same type as \tcode{D},
      or \tcode{D} is not a reference type and \tcode{E} is implicitly convertible to \tcode{D}.
\end{itemize}

\begin{note}
This replaces the \constraints specification of the primary template.
\end{note}
\end{itemdescr}

\rSec4[unique.ptr.runtime.asgn]{Assignment}

\indexlibrarymember{operator=}{unique_ptr}%
\begin{itemdecl}
template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
This operator behaves the same as in the primary template.

\pnum
\constraints
Where \tcode{UP} is \tcode{unique_ptr<U, E>}:
\begin{itemize}
\item \tcode{U} is an array type, and
\item \tcode{pointer} is the same type as \tcode{element_type*}, and
\item \tcode{UP::pointer} is the same type as \tcode{UP::element_type*}, and
\item \tcode{UP::element_type(*)[]} is convertible to \tcode{element_type(*)[]}, and
\item \tcode{is_assignable_v<D\&, E\&\&>} is \tcode{true}.
\end{itemize}

\begin{note}
This replaces the \constraints specification of the primary template.
\end{note}
\end{itemdescr}

\rSec4[unique.ptr.runtime.observers]{Observers}

\indexlibrarymember{operator[]}{unique_ptr}%
\begin{itemdecl}
constexpr T& operator[](size_t i) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$\tcode{i} <$ the
number of elements in the array to which
the stored pointer points.

\pnum
\returns
\tcode{get()[i]}.
\end{itemdescr}

\rSec4[unique.ptr.runtime.modifiers]{Modifiers}

\indexlibrarymember{reset}{unique_ptr}%
\begin{itemdecl}
constexpr void reset(nullptr_t p = nullptr) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{reset(pointer())}.
\end{itemdescr}

\indexlibrarymember{reset}{unique_ptr}%
\begin{itemdecl}
template<class U> constexpr void reset(U p) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
This function behaves the same as
the \tcode{reset} member of the primary template.

\pnum
\constraints
\begin{itemize}
\item \tcode{U} is the same type as \tcode{pointer}, or
\item \tcode{pointer} is the same type as \tcode{element_type*},
      \tcode{U} is a pointer type \tcode{V*}, and
      \tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}.
\end{itemize}
\end{itemdescr}

\rSec3[unique.ptr.create]{Creation}

\indexlibraryglobal{make_unique}%
\begin{itemdecl}
template<class T, class... Args> constexpr unique_ptr<T> make_unique(Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is not an array type.

\pnum
\returns
\tcode{unique_ptr<T>(new T(std::forward<Args>(args)...))}.

\end{itemdescr}

\indexlibraryglobal{make_unique}%
\begin{itemdecl}
template<class T> constexpr unique_ptr<T> make_unique(size_t n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is an array of unknown bound.

\pnum
\returns
\tcode{unique_ptr<T>(new remove_extent_t<T>[n]())}.

\end{itemdescr}

\indexlibraryglobal{make_unique}%
\begin{itemdecl}
template<class T, class... Args> @\unspec@ make_unique(Args&&...) = delete;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is an array of known bound.

\end{itemdescr}

\indexlibraryglobal{make_unique}%
\begin{itemdecl}
template<class T> constexpr unique_ptr<T> make_unique_for_overwrite();
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is not an array type.

\pnum
\returns
\tcode{unique_ptr<T>(new T)}.
\end{itemdescr}

\indexlibraryglobal{make_unique}%
\begin{itemdecl}
template<class T> constexpr unique_ptr<T> make_unique_for_overwrite(size_t n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is an array of unknown bound.

\pnum
\returns
\tcode{unique_ptr<T>(new remove_extent_t<T>[n])}.
\end{itemdescr}

\indexlibraryglobal{make_unique}%
\begin{itemdecl}
template<class T, class... Args> @\unspec@ make_unique_for_overwrite(Args&&...) = delete;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is an array of known bound.
\end{itemdescr}

\rSec3[unique.ptr.special]{Specialized algorithms}

\indexlibrary{\idxcode{swap(unique_ptr\&, unique_ptr\&)}}%
\begin{itemdecl}
template<class T, class D> constexpr void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_swappable_v<D>} is \tcode{true}.

\pnum
\effects
Calls \tcode{x.swap(y)}.
\end{itemdescr}

\indexlibrarymember{operator==}{unique_ptr}%
\begin{itemdecl}
template<class T1, class D1, class T2, class D2>
  constexpr bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.get() == y.get()}.
\end{itemdescr}

\indexlibrarymember{operator<}{unique_ptr}%
\begin{itemdecl}
template<class T1, class D1, class T2, class D2>
  constexpr bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{CT} denote
\begin{codeblock}
common_type_t<typename unique_ptr<T1, D1>::pointer,
              typename unique_ptr<T2, D2>::pointer>
\end{codeblock}

\pnum
\mandates
\begin{itemize}
\item \tcode{unique_ptr<T1, D1>::pointer} is implicitly convertible to \tcode{CT} and
\item \tcode{unique_ptr<T2, D2>::pointer} is implicitly convertible to \tcode{CT}.
\end{itemize}

\pnum
\expects
The specialization
\tcode{less<CT>} is a function object type\iref{function.objects} that
induces a strict weak ordering\iref{alg.sorting} on the pointer values.

\pnum
\returns
\tcode{less<CT>()(x.get(), y.get())}.
\end{itemdescr}

\indexlibrarymember{operator>}{unique_ptr}%
\begin{itemdecl}
template<class T1, class D1, class T2, class D2>
  constexpr bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{y < x}.
\end{itemdescr}

\indexlibrarymember{operator<=}{unique_ptr}%
\begin{itemdecl}
template<class T1, class D1, class T2, class D2>
  constexpr bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{!(y < x)}.
\end{itemdescr}

\indexlibrarymember{operator>=}{unique_ptr}%
\begin{itemdecl}
template<class T1, class D1, class T2, class D2>
  constexpr bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{!(x < y)}.
\end{itemdescr}

\indexlibrarymember{operator<=>}{unique_ptr}%
\begin{itemdecl}
template<class T1, class D1, class T2, class D2>
  requires @\libconcept{three_way_comparable_with}@<typename unique_ptr<T1, D1>::pointer,
                                     typename unique_ptr<T2, D2>::pointer>
  constexpr 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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{compare_three_way()(x.get(), y.get())}.
\end{itemdescr}

\indexlibrarymember{operator==}{unique_ptr}%
\begin{itemdecl}
template<class T, class D>
  constexpr bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{!x}.
\end{itemdescr}

\indexlibrarymember{operator<}{unique_ptr}%
\begin{itemdecl}
template<class T, class D>
  constexpr bool operator<(const unique_ptr<T, D>& x, nullptr_t);
template<class T, class D>
  constexpr bool operator<(nullptr_t, const unique_ptr<T, D>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
The specialization \tcode{less<unique_ptr<T, D>::pointer>} is
a function object type\iref{function.objects} that induces a strict weak
ordering\iref{alg.sorting} on the pointer values.

\pnum
\returns
The first function template returns
\begin{codeblock}
less<unique_ptr<T, D>::pointer>()(x.get(), nullptr)
\end{codeblock}
The second function template returns
\begin{codeblock}
less<unique_ptr<T, D>::pointer>()(nullptr, x.get())
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator>}{unique_ptr}%
\begin{itemdecl}
template<class T, class D>
  constexpr bool operator>(const unique_ptr<T, D>& x, nullptr_t);
template<class T, class D>
  constexpr bool operator>(nullptr_t, const unique_ptr<T, D>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The first function template returns \tcode{nullptr < x}.
The second function template returns \tcode{x < nullptr}.
\end{itemdescr}

\indexlibrarymember{operator<=}{unique_ptr}%
\begin{itemdecl}
template<class T, class D>
  constexpr bool operator<=(const unique_ptr<T, D>& x, nullptr_t);
template<class T, class D>
  constexpr bool operator<=(nullptr_t, const unique_ptr<T, D>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The first function template returns \tcode{!(nullptr < x)}.
The second function template returns \tcode{!(x < nullptr)}.
\end{itemdescr}

\indexlibrarymember{operator>=}{unique_ptr}%
\begin{itemdecl}
template<class T, class D>
  constexpr bool operator>=(const unique_ptr<T, D>& x, nullptr_t);
template<class T, class D>
  constexpr bool operator>=(nullptr_t, const unique_ptr<T, D>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The first function template returns \tcode{!(x < nullptr)}.
The second function template returns \tcode{!(nullptr < x)}.
\end{itemdescr}

\indexlibrarymember{operator<=>}{unique_ptr}%
\begin{itemdecl}
template<class T, class D>
  requires @\libconcept{three_way_comparable}@<typename unique_ptr<T, D>::pointer>
  constexpr compare_three_way_result_t<typename unique_ptr<T, D>::pointer>
    operator<=>(const unique_ptr<T, D>& x, nullptr_t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{codeblock}
compare_three_way()(x.get(), static_cast<typename unique_ptr<T, D>::pointer>(nullptr)).
\end{codeblock}
\end{itemdescr}

\rSec3[unique.ptr.io]{I/O}

\indexlibrarymember{operator<<}{unique_ptr}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{os << p.get()} is a valid expression.

\pnum
\effects
Equivalent to: \tcode{os << p.get();}

\pnum
\returns
\tcode{os}.
\end{itemdescr}

\rSec2[util.sharedptr]{Shared-ownership pointers}

\rSec3[util.smartptr.weak.bad]{Class \tcode{bad_weak_ptr}}%
\indextext{smart pointers|(}%

\indexlibraryglobal{bad_weak_ptr}%
\begin{codeblock}
namespace std {
  class bad_weak_ptr : public exception {
  public:
    // see \ref{exception} for the specification of the special member functions
    constexpr const char* what() const noexcept override;
  };
}
\end{codeblock}

\pnum
An exception of type \tcode{bad_weak_ptr} is thrown by the \tcode{shared_ptr}
constructor taking a \tcode{weak_ptr}.

\indexlibrarymember{what}{bad_weak_ptr}%
\begin{itemdecl}
constexpr const char* what() const noexcept override;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An \impldef{return value of \tcode{bad_weak_ptr::what}} \ntbs{}.
\end{itemdescr}

\rSec3[util.smartptr.shared]{Class template \tcode{shared_ptr}}

\rSec4[util.smartptr.shared.general]{General}

\pnum
\indexlibraryglobal{shared_ptr}%
The \tcode{shared_ptr} class template stores a pointer, usually obtained
via \keyword{new}. \tcode{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
\tcode{shared_ptr} is said to be empty if it does not own a pointer.

\begin{codeblock}
namespace std {
  template<class T> class shared_ptr {
  public:
    using element_type = remove_extent_t<T>;
    using weak_type    = weak_ptr<T>;

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

    // \ref{util.smartptr.shared.dest}, destructor
    constexpr ~shared_ptr();

    // \ref{util.smartptr.shared.assign}, assignment
    constexpr shared_ptr& operator=(const shared_ptr& r) noexcept;
    template<class Y>
      constexpr shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    constexpr shared_ptr& operator=(shared_ptr&& r) noexcept;
    template<class Y>
      constexpr shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
    template<class Y, class D>
      constexpr shared_ptr& operator=(unique_ptr<Y, D>&& r);

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

    // \ref{util.smartptr.shared.obs}, observers
    constexpr element_type* get() const noexcept;
    constexpr T& operator*() const noexcept;
    constexpr T* operator->() const noexcept;
    constexpr element_type& operator[](ptrdiff_t i) const;
    constexpr long use_count() const noexcept;
    constexpr 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;
    size_t owner_hash() const noexcept;
    template<class U>
      constexpr bool owner_equal(const shared_ptr<U>& b) const noexcept;
    template<class U>
      constexpr bool owner_equal(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>;
}
\end{codeblock}

\pnum
Specializations of \tcode{shared_ptr} shall be \oldconceptref{CopyConstructible},
\oldconceptref{CopyAssignable}, and \oldconceptref{LessThanComparable}, allowing their use in standard
containers. Specializations of \tcode{shared_ptr} shall be
contextually convertible to \tcode{bool},
allowing their use in boolean expressions and declarations in conditions.

\pnum
The template parameter \tcode{T} of \tcode{shared_ptr}
may be an incomplete type.
\begin{note}
\tcode{T} can be a function type.
\end{note}

\pnum
\begin{example}
\begin{codeblock}
if (shared_ptr<X> px = dynamic_pointer_cast<X>(py)) {
  // do something with \tcode{px}
}
\end{codeblock}
\end{example}

\pnum
For purposes of determining the presence of a data race, member functions shall
access and modify only the \tcode{shared_ptr} and \tcode{weak_ptr} objects
themselves and not objects they refer to. Changes in \tcode{use_count()} do not
reflect modifications that can introduce data races.

\pnum
For the purposes of \ref{smartptr},
a pointer type \tcode{Y*} is said to be
\defnx{compatible with}{compatible with!\idxcode{shared_ptr}}
a pointer type \tcode{T*} when either
\tcode{Y*} is convertible to \tcode{T*} or
\tcode{Y} is \tcode{U[N]} and \tcode{T} is \cv{}~\tcode{U[]}.

\rSec4[util.smartptr.shared.const]{Constructors}

\pnum
In the constructor definitions below,
enables \tcode{shared_from_this} with \tcode{p},
for a pointer \tcode{p} of type \tcode{Y*},
means that if \tcode{Y} has an unambiguous and accessible base class
that is a specialization of \tcode{enable_shared_from_this}\iref{util.smartptr.enab},
then \tcode{remove_cv_t<Y>*} shall be implicitly convertible to \tcode{T*} and
the constructor evaluates the statement:
\begin{codeblock}
if (p != nullptr && p->@\exposid{weak-this}@.expired())
  p->@\exposid{weak-this}@ = shared_ptr<remove_cv_t<Y>>(*this, const_cast<remove_cv_t<Y>*>(p));
\end{codeblock}
The assignment to the \exposid{weak-this} member is not atomic and
conflicts with any potentially concurrent access to the same object\iref{intro.multithread}.

\indexlibraryctor{shared_ptr}%
\begin{itemdecl}
constexpr shared_ptr() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{use_count() == 0 \&\& get() == nullptr}.
\end{itemdescr}

\indexlibraryctor{shared_ptr}%
\begin{itemdecl}
template<class Y> constexpr explicit shared_ptr(Y* p);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
When \tcode{T} is an array type,
the expression \tcode{delete[] p} is well-formed and either
\tcode{T} is \tcode{U[N]} and \tcode{Y(*)[N]} is convertible to \tcode{T*}, or
\tcode{T} is \tcode{U[]} and \tcode{Y(*)[]} is convertible to \tcode{T*}.
When \tcode{T} is not an array type,
the expression \tcode{delete p} is well-formed and
\tcode{Y*} is convertible to \tcode{T*}.

\pnum
\mandates
\tcode{Y} is a complete type.

\pnum
\expects
The expression
\tcode{delete[] p}, when \tcode{T} is an array type, or
\tcode{delete p}, when \tcode{T} is not an array type,
has well-defined behavior, and
does not throw exceptions.

\pnum
\effects
When \tcode{T} is not an array type,
constructs a \tcode{shared_ptr} object
that owns the pointer \tcode{p}.
Otherwise, constructs a \tcode{shared_ptr}
that owns \tcode{p} and a deleter of an
unspecified type that calls \tcode{delete[] p}.
When \tcode{T} is not an array type,
enables \tcode{shared_from_this} with \tcode{p}.
If an exception is thrown, \tcode{delete p} is called
when \tcode{T} is not an array type, \tcode{delete[] p} otherwise.

\pnum
\ensures
\tcode{use_count() == 1 \&\& get() == p}.

\pnum
\throws
\tcode{bad_alloc}, or an \impldef{exception type when \tcode{shared_ptr}
constructor fails} exception when a resource other than memory cannot be obtained.
\end{itemdescr}

\indexlibraryctor{shared_ptr}%
\begin{itemdecl}
template<class Y, class D> constexpr shared_ptr(Y* p, D d);
template<class Y, class D, class A> constexpr shared_ptr(Y* p, D d, A a);
template<class D> constexpr shared_ptr(nullptr_t p, D d);
template<class D, class A> constexpr shared_ptr(nullptr_t p, D d, A a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_move_constructible_v<D>} is \tcode{true}, and
\tcode{d(p)} is a well-formed expression.
For the first two overloads:
\begin{itemize}
\item
If \tcode{T} is an array type, then either
\tcode{T} is \tcode{U[N]} and \tcode{Y(*)[N]} is convertible to \tcode{T*}, or
\tcode{T} is \tcode{U[]} and \tcode{Y(*)[]} is convertible to \tcode{T*}.

\item
If \tcode{T} is not an array type, then \tcode{Y*} is convertible to \tcode{T*}.
\end{itemize}

\pnum
\expects
Construction of \tcode{d} and a deleter of type \tcode{D}
initialized with \tcode{std::move(d)} do not throw exceptions.
The expression \tcode{d(p)}
has well-defined behavior and does not throw exceptions.
\tcode{A} meets
the \oldconceptref{Allocator} requirements\iref{allocator.requirements.general}.

\pnum
\effects
Constructs a \tcode{shared_ptr} object that owns the
object \tcode{p} and the deleter \tcode{d}.
When \tcode{T} is not an array type,
the first and second constructors enable \tcode{shared_from_this} with \tcode{p}.
The second and fourth constructors shall use a copy of \tcode{a} to
allocate memory for internal use.
If an exception is thrown, \tcode{d(p)} is called.

\pnum
\ensures
\tcode{use_count() == 1 \&\& get() == p}.

\pnum
\throws
\tcode{bad_alloc}, or an \impldef{exception type when \tcode{shared_ptr}
constructor fails} exception
when a resource other than memory cannot be obtained.
\end{itemdescr}

\indexlibraryctor{shared_ptr}%
\begin{itemdecl}
template<class Y> constexpr shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;
template<class Y> constexpr shared_ptr(shared_ptr<Y>&& r, element_type* p) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{shared_ptr} instance that
stores \tcode{p} and shares ownership with
the initial value of \tcode{r}.

\pnum
\ensures
\tcode{get() == p}.
For the second overload,
\tcode{r} is empty and \tcode{r.get() == nullptr}.

\pnum
\begin{note}
Use of this constructor leads to a dangling pointer
unless \tcode{p} remains valid
at least until the ownership group of \tcode{r} is destroyed.
\end{note}

\pnum
\begin{note}
This constructor allows creation of an empty
\tcode{shared_ptr} instance with a non-null stored pointer.
\end{note}
\end{itemdescr}

\indexlibraryctor{shared_ptr}%
\begin{itemdecl}
constexpr shared_ptr(const shared_ptr& r) noexcept;
template<class Y> constexpr shared_ptr(const shared_ptr<Y>& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
For the second constructor, \tcode{Y*} is compatible with \tcode{T*}.

\pnum
\effects
If \tcode{r} is empty, constructs
an empty \tcode{shared_ptr} object; otherwise, constructs
a \tcode{shared_ptr} object that shares ownership with \tcode{r}.

\pnum
\ensures
\tcode{get() == r.get() \&\& use_count() == r.use_count()}.
\end{itemdescr}

\indexlibraryctor{shared_ptr}%
\begin{itemdecl}
constexpr shared_ptr(shared_ptr&& r) noexcept;
template<class Y> constexpr shared_ptr(shared_ptr<Y>&& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
For the second constructor, \tcode{Y*} is compatible with \tcode{T*}.

\pnum
\effects
Move constructs a \tcode{shared_ptr} instance from \tcode{r}.

\pnum
\ensures
\tcode{*this} contains the old value of
\tcode{r}. \tcode{r} is empty, and \tcode{r.get() == nullptr}.
\end{itemdescr}

\indexlibraryctor{shared_ptr}%
\indexlibraryglobal{weak_ptr}%
\begin{itemdecl}
template<class Y> constexpr explicit shared_ptr(const weak_ptr<Y>& r);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{Y*} is compatible with \tcode{T*}.

\pnum
\effects
Constructs a \tcode{shared_ptr} object that shares ownership with
\tcode{r} and stores a copy of the pointer stored in \tcode{r}.
If an exception is thrown, the constructor has no effect.

\pnum
\ensures
\tcode{use_count() == r.use_count()}.

\pnum
\throws
\tcode{bad_weak_ptr} when \tcode{r.expired()}.
\end{itemdescr}

\indexlibraryctor{shared_ptr}%
\indexlibraryglobal{unique_ptr}%
\begin{itemdecl}
template<class Y, class D> constexpr shared_ptr(unique_ptr<Y, D>&& r);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{Y*} is compatible with \tcode{T*} and
\tcode{unique_ptr<Y, D>::pointer} is convertible to \tcode{element_type*}.

\pnum
\effects
If \tcode{r.get() == nullptr}, equivalent to \tcode{shared_ptr()}.
Otherwise, if \tcode{D} is not a reference type,
equivalent to \tcode{shared_ptr(r.release(), std::move(r.get_deleter()))}.
Otherwise, equivalent to \tcode{shared_ptr(r.release(), ref(r.get_deleter()))}.
If an exception is thrown, the constructor has no effect.
\end{itemdescr}

\rSec4[util.smartptr.shared.dest]{Destructor}

\indexlibrarydtor{shared_ptr}%
\begin{itemdecl}
constexpr ~shared_ptr();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\begin{itemize}
\item If \tcode{*this} is empty or shares ownership with another
\tcode{shared_ptr} instance (\tcode{use_count() > 1}), there are no side effects.

\item
Otherwise, if \tcode{*this} owns an object
\tcode{p} and a deleter \tcode{d}, \tcode{d(p)} is called.

\item Otherwise, \tcode{*this} owns a pointer \tcode{p},
and \tcode{delete p} is called.
\end{itemize}
\end{itemdescr}

\pnum
\begin{note}
Since the destruction of \tcode{*this}
decreases the number of instances that share ownership with \tcode{*this}
by one,
after \tcode{*this} has been destroyed
all \tcode{shared_ptr} instances that shared ownership with
\tcode{*this} will report a \tcode{use_count()} that is one less
than its previous value.
\end{note}

\rSec4[util.smartptr.shared.assign]{Assignment}

\indexlibrarymember{operator=}{shared_ptr}%
\begin{itemdecl}
constexpr shared_ptr& operator=(const shared_ptr& r) noexcept;
template<class Y> constexpr shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{shared_ptr(r).swap(*this)}.

\pnum
\returns
\tcode{*this}.

\pnum
\begin{note}
The use count updates caused by the temporary object
construction and destruction are not observable side
effects, so the implementation can meet the effects (and the
implied guarantees) via different means, without creating a
temporary. In particular, in the example:
\begin{codeblock}
shared_ptr<int> p(new int);
shared_ptr<void> q(p);
p = p;
q = p;
\end{codeblock}
both assignments can be no-ops.
\end{note}
\end{itemdescr}

\indexlibrarymember{operator=}{shared_ptr}%
\begin{itemdecl}
constexpr shared_ptr& operator=(shared_ptr&& r) noexcept;
template<class Y> constexpr shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{shared_ptr(std::move(r)).swap(*this)}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator=}{shared_ptr}%
\begin{itemdecl}
template<class Y, class D> constexpr shared_ptr& operator=(unique_ptr<Y, D>&& r);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{shared_ptr(std::move(r)).swap(*this)}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\rSec4[util.smartptr.shared.mod]{Modifiers}

\indexlibrarymember{swap}{shared_ptr}%
\begin{itemdecl}
constexpr void swap(shared_ptr& r) noexcept;
\end{itemdecl}

\begin{itemdescr}

\pnum
\effects
Exchanges the contents of \tcode{*this} and \tcode{r}.
\end{itemdescr}

\indexlibrarymember{reset}{shared_ptr}%
\begin{itemdecl}
constexpr void reset() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{shared_ptr().swap(*this)}.
\end{itemdescr}

\indexlibrarymember{reset}{shared_ptr}%
\begin{itemdecl}
template<class Y> constexpr void reset(Y* p);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{shared_ptr(p).swap(*this)}.
\end{itemdescr}

\indexlibrarymember{reset}{shared_ptr}%
\begin{itemdecl}
template<class Y, class D> constexpr void reset(Y* p, D d);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{shared_ptr(p, d).swap(*this)}.
\end{itemdescr}

\indexlibrarymember{reset}{shared_ptr}%
\begin{itemdecl}
template<class Y, class D, class A> constexpr void reset(Y* p, D d, A a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{shared_ptr(p, d, a).swap(*this)}.
\end{itemdescr}

\rSec4[util.smartptr.shared.obs]{Observers}
\indexlibrarymember{get}{shared_ptr}%
\begin{itemdecl}
constexpr element_type* get() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The stored pointer.
\end{itemdescr}

\indexlibrarymember{operator*}{shared_ptr}%
\begin{itemdecl}
constexpr T& operator*() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{get() != nullptr}.

\pnum
\returns
\tcode{*get()}.

\pnum
\remarks
When \tcode{T} is an array type or \cv{}~\keyword{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.
\end{itemdescr}

\indexlibrarymember{operator->}{shared_ptr}%
\begin{itemdecl}
constexpr T* operator->() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{get() != nullptr}.

\pnum
\returns
\tcode{get()}.

\pnum
\remarks
When \tcode{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.
\end{itemdescr}

\indexlibrarymember{operator[]}{shared_ptr}%
\begin{itemdecl}
constexpr element_type& operator[](ptrdiff_t i) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{get() != nullptr} is \tcode{true}.

\pnum
\hardexpects
$\tcode{i} \ge 0$. If \tcode{T} is \tcode{U[N]}, $\tcode{i} < \tcode{N}$.

\pnum
\returns
\tcode{get()[i]}.

\pnum
\throws
Nothing.

\pnum
\remarks
When \tcode{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.
\end{itemdescr}

\indexlibrarymember{use_count}{shared_ptr}%
\begin{itemdecl}
constexpr long use_count() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\sync
None.

\pnum
\returns
The number of \tcode{shared_ptr} objects, \tcode{*this} included,
that share ownership with \tcode{*this}, or \tcode{0} when \tcode{*this} is
empty.

\pnum
\begin{note}
\tcode{get() == nullptr}
does not imply a specific return value of \tcode{use_count()}.
\end{note}

\pnum
\begin{note}
\tcode{weak_ptr<T>::lock()}
can affect the return value of \tcode{use_count()}.
\end{note}

\pnum
\begin{note}
When multiple threads
might affect the return value of \tcode{use_count()},
the result is approximate.
In particular, \tcode{use_count() == 1} does not imply that accesses through
a previously destroyed \tcode{shared_ptr} have in any sense completed.
\end{note}
\end{itemdescr}

\indexlibrarymember{operator bool}{shared_ptr}%
\begin{itemdecl}
constexpr explicit operator bool() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{get() != nullptr}.
\end{itemdescr}

\indexlibrarymember{owner_before}{shared_ptr}%
\begin{itemdecl}
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;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An unspecified value such that
\begin{itemize}
\item
\tcode{owner_before(b)} defines a strict weak ordering as defined in~\ref{alg.sorting};
\item
\tcode{!owner_before(b) \&\& !b.owner_before(*this)} is \tcode{true}
if and only if \tcode{owner_equal(b)} is \tcode{true}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{owner_hash}{shared_ptr}%
\begin{itemdecl}
size_t owner_hash() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An unspecified value such that,
for any object \tcode{x} where \tcode{owner_equal(x)} is \tcode{true},
\tcode{owner_hash() == x.owner_hash()} is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{owner_equal}{shared_ptr}%
\begin{itemdecl}
template<class U>
  constexpr bool owner_equal(const shared_ptr<U>& b) const noexcept;
template<class U>
  constexpr bool owner_equal(const weak_ptr<U>& b) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if and only if
\tcode{*this} and \tcode{b} share ownership or are both empty.
Otherwise returns \tcode{false}.

\pnum
\remarks
\tcode{owner_equal} is an equivalence relation.
\end{itemdescr}

\rSec4[util.smartptr.shared.create]{Creation}

\pnum
The common requirements that apply to all
\tcode{make_shared},
\tcode{allocate_shared},
\tcode{make_shared_for_overwrite}, and
\tcode{allocate_shared_for_overwrite} overloads,
unless specified otherwise, are described below.

\indexlibraryglobal{make_shared}%
\indexlibraryglobal{allocate_shared}%
\begin{itemdecl}
template<class T, ...>
  constexpr shared_ptr<T> make_shared(@\placeholdernc{args}@);
template<class T, class A, ...>
  constexpr shared_ptr<T> allocate_shared(const A& a, @\placeholdernc{args}@);
template<class T, ...>
  constexpr shared_ptr<T> make_shared_for_overwrite(@\placeholdernc{args}@);
template<class T, class A, ...>
  constexpr shared_ptr<T> allocate_shared_for_overwrite(const A& a, @\placeholdernc{args}@);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{A} meets
the \oldconceptref{Allocator} requirements\iref{allocator.requirements.general}.

\pnum
\effects
Allocates memory for an object of type \tcode{T}
(or \tcode{U[N]} when \tcode{T} is \tcode{U[]},
where \tcode{N} is determined from \placeholder{args} as specified by the concrete overload).
The object is initialized from \placeholder{args} as specified by the concrete overload.
The \tcode{allocate_shared} and \tcode{allocate_shared_for_overwrite} templates
use a copy of \tcode{a}
(rebound for an unspecified \tcode{value_type}) to allocate memory.
If an exception is thrown, the functions have no effect.

\pnum
\ensures
\tcode{r.get() != nullptr \&\& r.use_count() == 1},
where \tcode{r} is the return value.

\pnum
\returns
A \tcode{shared_ptr} instance that stores and owns the address of
the newly constructed object.

\pnum
\throws
\tcode{bad_alloc}, or
an exception thrown from \tcode{allocate} or from the initialization of the object.

\pnum
\remarks
\begin{itemize}
\item
  Implementations should perform no more than one memory allocation.
  \begin{note}
  This provides efficiency equivalent to an intrusive smart pointer.
  \end{note}
\item
  When an object of an array type \tcode{U} is specified to have
  an initial value of \tcode{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 \tcode{u}.
\item
  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.
\item
  When a (sub)object of a non-array type \tcode{U} is specified to have
  an initial value of \tcode{v}, or \tcode{U(l...)},
  where \tcode{l...} is a list of constructor arguments,
  \tcode{make_shared} shall initialize this (sub)object
  via the expression \tcode{::new(pv) U(v)} or \tcode{::new(pv) U(l...)} respectively,
  where \tcode{pv} has type \tcode{void*} and points to storage
  suitable to hold an object of type \tcode{U}.
\item
  When a (sub)object of a non-array type \tcode{U} is specified to have
  an initial value of \tcode{v}, or \tcode{U(l...)},
  where \tcode{l...} is a list of constructor arguments,
  \tcode{allocate_shared} shall initialize this (sub)object
  via the expression
  \begin{itemize}
  \item \tcode{allocator_traits<A2>::construct(a2, pu, v)} or
  \item \tcode{allocator_traits<A2>::construct(a2, pu, l...)}
  \end{itemize}
  respectively,
  where \tcode{pu} is a pointer of type \tcode{remove_cv_t<U>*}
  pointing to storage
  suitable to hold an object of type \tcode{remove_cv_t<U>} and
  \tcode{a2} of type \tcode{A2} is a potentially rebound copy of
  the allocator \tcode{a} passed to \tcode{allocate_shared}.
\item
  When a (sub)object of non-array type \tcode{U} is specified to have
  a default initial value,
  \tcode{make_shared} shall initialize this (sub)object
  via the expression \tcode{::new(pv) U()},
  where \tcode{pv} has type \tcode{void*} and points to storage
  suitable to hold an object of type \tcode{U}.
\item
  When a (sub)object of non-array type \tcode{U} is specified to have
  a default initial value,
  \tcode{allocate_shared} initializes this (sub)object
  via the expression \tcode{allocator_traits<A2>::construct(a2, pu)},
  where \tcode{pu} is a pointer of type \tcode{remove_cv_t<U>*}
  pointing to storage
  suitable to hold an object of type \tcode{remove_cv_t<U>} and
  \tcode{a2} of type \tcode{A2} is a potentially rebound copy of
  the allocator \tcode{a} passed to \tcode{allocate_shared}.
\item
  When a (sub)object of non-array type \tcode{U} is initialized by
  \tcode{make_shared_for_overwrite} or
  \tcode{allocate_shared_for_overwrite},
  it is initialized via the expression \tcode{::new(pv) U},
  where \tcode{pv} has type \tcode{void*} and
  points to storage suitable to hold an object of type \tcode{U}.
\item
  Array elements are initialized in ascending order of their addresses.
\item
  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.
\item
  When a (sub)object of non-array type \tcode{U}
  that was initialized by \tcode{make_shared},
  \tcode{make_shared_for_overwrite}, or \tcode{allocate_shared_for_overwrite}
  is to be destroyed,
  it is destroyed via the expression \tcode{pu->\~{}U()} where
  \tcode{pu} points to that object of type \tcode{U}.
\item
  When a (sub)object of non-array type \tcode{U}
  that was initialized by \tcode{allocate_shared} is to be destroyed,
  it is destroyed via the expression
  \tcode{allocator_traits<A2>::destroy(a2, pu)} where
  \tcode{pu} is a pointer of type \tcode{remove_cv_t<U>*}
  pointing to that object of type \tcode{remove_cv_t<U>} and
  \tcode{a2} of type \tcode{A2} is a potentially rebound copy of
  the allocator \tcode{a} passed to \tcode{allocate_shared}.
\end{itemize}
\begin{note}
These functions will typically allocate more memory than \tcode{sizeof(T)} to
allow for internal bookkeeping structures such as reference counts.
\end{note}
\end{itemdescr}

\indexlibraryglobal{make_shared}%
\indexlibraryglobal{allocate_shared}%
\begin{itemdecl}
template<class T, class... Args>
  constexpr shared_ptr<T> make_shared(Args&&... args);                    // \tcode{T} is not array
template<class T, class A, class... Args>
  constexpr shared_ptr<T> allocate_shared(const A& a, Args&&... args);    // \tcode{T} is not array
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is not an array type.

\pnum
\returns
A \tcode{shared_ptr} to an object of type \tcode{T}
with an initial value \tcode{T(std::forward<Args>(args)...)}.

\pnum
\remarks
The \tcode{shared_ptr} constructors called by these functions
enable \tcode{shared_from_this}
with the address of the newly constructed object of type \tcode{T}.

\pnum
\begin{example}
\begin{codeblock}
shared_ptr<int> p = make_shared<int>(); // \tcode{shared_ptr} to \tcode{int()}
shared_ptr<vector<int>> q = make_shared<vector<int>>(16, 1);
  // \tcode{shared_ptr} to vector of \tcode{16} elements with value \tcode{1}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibraryglobal{make_shared}%
\indexlibraryglobal{allocate_shared}%
\begin{itemdecl}
template<class T>
  constexpr shared_ptr<T> make_shared(size_t N);                          // \tcode{T} is \tcode{U[]}
template<class T, class A>
  constexpr shared_ptr<T> allocate_shared(const A& a, size_t N);          // \tcode{T} is \tcode{U[]}
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is an array of unknown bound.

\pnum
\returns
A \tcode{shared_ptr} to an array of
\tcode{N} elements of type \tcode{remove_extent_t<T>}
with a default initial value.

\pnum
\begin{example}
\begin{codeblock}
shared_ptr<double[]> p = make_shared<double[]>(1024);
  // \tcode{shared_ptr} to a value-initialized \tcode{double[1024]}
shared_ptr<double[][2][2]> q = make_shared<double[][2][2]>(6);
  // \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibraryglobal{make_shared}%
\indexlibraryglobal{allocate_shared}%
\begin{itemdecl}
template<class T>
  constexpr shared_ptr<T> make_shared();                                  // \tcode{T} is \tcode{U[N]}
template<class T, class A>
  constexpr shared_ptr<T> allocate_shared(const A& a);                    // \tcode{T} is \tcode{U[N]}
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is an array of known bound.

\pnum
\returns
A \tcode{shared_ptr} to an object of type \tcode{T}
with a default initial value.

\pnum
\begin{example}
\begin{codeblock}
shared_ptr<double[1024]> p = make_shared<double[1024]>();
  // \tcode{shared_ptr} to a value-initialized \tcode{double[1024]}
shared_ptr<double[6][2][2]> q = make_shared<double[6][2][2]>();
  // \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibraryglobal{make_shared}%
\indexlibraryglobal{allocate_shared}%
\begin{itemdecl}
template<class T>
  constexpr shared_ptr<T> make_shared(size_t N,
                                      const remove_extent_t<T>& u);     // \tcode{T} is \tcode{U[]}
template<class T, class A>
  constexpr shared_ptr<T> allocate_shared(const A& a, size_t N,
                                          const remove_extent_t<T>& u); // \tcode{T} is \tcode{U[]}
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is an array of unknown bound.

\pnum
\returns
A \tcode{shared_ptr} to an array of
\tcode{N} elements of type \tcode{remove_extent_t<T>}
where each array element has an initial value of \tcode{u}.

\pnum
\begin{example}
\begin{codeblock}
shared_ptr<double[]> p = make_shared<double[]>(1024, 1.0);
  // \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0}
shared_ptr<double[][2]> q = make_shared<double[][2]>(6, {1.0, 0.0});
  // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each \tcode{double[2]} element is \tcode{\{1.0, 0.0\}}
shared_ptr<vector<int>[]> r = make_shared<vector<int>[]>(4, {1, 2});
  // \tcode{shared_ptr} to a \tcode{vector<int>[4]}, where each vector has contents \tcode{\{1, 2\}}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibraryglobal{make_shared}%
\indexlibraryglobal{allocate_shared}%
\begin{itemdecl}
template<class T>
  constexpr shared_ptr<T> make_shared(const remove_extent_t<T>& u);       // \tcode{T} is \tcode{U[N]}
template<class T, class A>
  constexpr shared_ptr<T> allocate_shared(const A& a,
                                          const remove_extent_t<T>& u);   // \tcode{T} is \tcode{U[N]}
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is an array of known bound.

\pnum
\returns
A \tcode{shared_ptr} to an object of type \tcode{T},
where each array element of type \tcode{remove_extent_t<T>}
has an initial value of \tcode{u}.

\pnum
\begin{example}
\begin{codeblock}
shared_ptr<double[1024]> p = make_shared<double[1024]>(1.0);
  // \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0}
shared_ptr<double[6][2]> q = make_shared<double[6][2]>({1.0, 0.0});
  // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each \tcode{double[2]} element is \tcode{\{1.0, 0.0\}}
shared_ptr<vector<int>[4]> r = make_shared<vector<int>[4]>({1, 2});
  // \tcode{shared_ptr} to a \tcode{vector<int>[4]}, where each vector has contents \tcode{\{1, 2\}}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibraryglobal{make_shared}%
\indexlibraryglobal{allocate_shared}%
\begin{itemdecl}
template<class T>
  constexpr shared_ptr<T> make_shared_for_overwrite();
template<class T, class A>
  constexpr shared_ptr<T> allocate_shared_for_overwrite(const A& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is not an array of unknown bound.

\pnum
\returns
A \tcode{shared_ptr} to an object of type \tcode{T}.

\pnum
\begin{example}
\begin{codeblock}
struct X { double data[1024]; };
shared_ptr<X> p = make_shared_for_overwrite<X>();
  // \tcode{shared_ptr} to a default-initialized \tcode{X}, where each element in \tcode{X::data} has an indeterminate value

shared_ptr<double[1024]> q = make_shared_for_overwrite<double[1024]>();
  // \tcode{shared_ptr} to a default-initialized \tcode{double[1024]}, where each element has an indeterminate value
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibraryglobal{make_shared}%
\indexlibraryglobal{allocate_shared}%
\begin{itemdecl}
template<class T>
  constexpr shared_ptr<T> make_shared_for_overwrite(size_t N);
template<class T, class A>
  constexpr shared_ptr<T> allocate_shared_for_overwrite(const A& a, size_t N);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is an array of unknown bound.

\pnum
\returns
A \tcode{shared_ptr} to an array of
\tcode{N} elements of type \tcode{remove_extent_t<T>}.

\pnum
\begin{example}
\begin{codeblock}
shared_ptr<double[]> p = make_shared_for_overwrite<double[]>(1024);
  // \tcode{shared_ptr} to a default-initialized \tcode{double[1024]}, where each element has an indeterminate value
\end{codeblock}
\end{example}
\end{itemdescr}

\rSec4[util.smartptr.shared.cmp]{Comparison}

\indexlibrarymember{operator==}{shared_ptr}%
\begin{itemdecl}
template<class T, class U>
  constexpr bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{a.get() == b.get()}.
\end{itemdescr}

\indexlibrarymember{operator==}{shared_ptr}%
\begin{itemdecl}
template<class T>
  constexpr bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{!a}.
\end{itemdescr}

\indexlibrarymember{operator<=>}{shared_ptr}%
\begin{itemdecl}
template<class T, class U>
  constexpr strong_ordering operator<=>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{compare_three_way()(a.get(), b.get())}.

\pnum
\begin{note}
Defining a comparison operator function allows \tcode{shared_ptr} objects
to be used as keys in associative containers.
\end{note}
\end{itemdescr}

\indexlibrarymember{operator<=>}{shared_ptr}%
\begin{itemdecl}
template<class T>
  constexpr strong_ordering operator<=>(const shared_ptr<T>& a, nullptr_t) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{codeblock}
compare_three_way()(a.get(), static_cast<typename shared_ptr<T>::element_type*>(nullptr))
\end{codeblock}
\end{itemdescr}

\rSec4[util.smartptr.shared.spec]{Specialized algorithms}

\indexlibrarymember{swap}{shared_ptr}%
\begin{itemdecl}
template<class T>
  constexpr void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{a.swap(b)}.
\end{itemdescr}

\rSec4[util.smartptr.shared.cast]{Casts}

\indexlibrarymember{static_pointer_cast}{shared_ptr}%
\begin{itemdecl}
template<class T, class U>
  constexpr shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
template<class T, class U>
  constexpr shared_ptr<T> static_pointer_cast(shared_ptr<U>&& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The expression \tcode{static_cast<T*>((U*)nullptr)} is well-formed.

\pnum
\returns
\begin{codeblock}
shared_ptr<T>(@\placeholder{R}@, static_cast<typename shared_ptr<T>::element_type*>(r.get()))
\end{codeblock}
where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and
\tcode{std::move(r)} for the second.

\pnum
\begin{note}
The seemingly equivalent expression
\tcode{shared_ptr<T>(static_cast<T*>(r.get()))}
can result in undefined behavior, attempting to delete the
same object twice.
\end{note}
\end{itemdescr}

\indexlibrarymember{dynamic_pointer_cast}{shared_ptr}%
\begin{itemdecl}
template<class T, class U>
  constexpr shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;
template<class T, class U>
  constexpr shared_ptr<T> dynamic_pointer_cast(shared_ptr<U>&& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The expression \tcode{dynamic_cast<T*>((U*)nullptr)} is well-formed.
The expression \tcode{dynamic_cast<typename shared_ptr<T>::element_type*>(r.get())} is well-formed.

\pnum
\expects
The expression \tcode{dynamic_cast<typename shared_ptr<T>::element_type*>(r.get())} has well-defined behavior.

\pnum
\returns
\begin{itemize}
\item When \tcode{dynamic_cast<typename shared_ptr<T>::element_type*>(r.get())}
  returns a non-null value \tcode{p},
  \tcode{shared_ptr<T>(\placeholder{R}, p)},
  where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and
  \tcode{std::move(r)} for the second.
\item Otherwise, \tcode{shared_ptr<T>()}.
\end{itemize}

\pnum
\begin{note}
The seemingly equivalent expression
\tcode{shared_ptr<T>(dynamic_cast<T*>(r.get()))} can result in
undefined behavior, attempting to delete the same object twice.
\end{note}
\end{itemdescr}

\indexlibrarymember{const_pointer_cast}{shared_ptr}%
\begin{itemdecl}
template<class T, class U>
  constexpr shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;
template<class T, class U>
  constexpr shared_ptr<T> const_pointer_cast(shared_ptr<U>&& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The expression \tcode{const_cast<T*>((U*)nullptr)} is well-formed.

\pnum
\returns
\begin{codeblock}
shared_ptr<T>(@\placeholder{R}@, const_cast<typename shared_ptr<T>::element_type*>(r.get()))
\end{codeblock}
where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and
\tcode{std::move(r)} for the second.

\pnum
\begin{note}
The seemingly equivalent expression
\tcode{shared_ptr<T>(const_cast<T*>(r.get()))} can result in
undefined behavior, attempting to delete the same object twice.
\end{note}
\end{itemdescr}

\indexlibrarymember{reinterpret_pointer_cast}{shared_ptr}%
\begin{itemdecl}
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;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The expression \tcode{reinterpret_cast<T*>((U*)nullptr)} is well-formed.

\pnum
\returns
\begin{codeblock}
shared_ptr<T>(@\placeholder{R}@, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()))
\end{codeblock}
where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and
\tcode{std::move(r)} for the second.

\pnum
\begin{note}
The seemingly equivalent expression
\tcode{shared_ptr<T>(reinterpret_cast<T*>(r.get()))} can result in
undefined behavior, attempting to delete the same object twice.
\end{note}
\end{itemdescr}

\rSec4[util.smartptr.getdeleter]{\tcode{get_deleter}}

\indexlibrarymember{get_deleter}{shared_ptr}%
\begin{itemdecl}
template<class D, class T>
  constexpr D* get_deleter(const shared_ptr<T>& p) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
If \tcode{p} owns a deleter \tcode{d} of type cv-unqualified
\tcode{D}, returns \tcode{addressof(d)}; otherwise returns \keyword{nullptr}.
The returned
pointer remains valid as long as there exists a \tcode{shared_ptr} instance
that owns \tcode{d}.
\begin{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 \tcode{weak_ptr} instances that share ownership with
\tcode{p} have been destroyed.
\end{note}
\end{itemdescr}

\rSec4[util.smartptr.shared.io]{I/O}

\indexlibrarymember{operator<<}{shared_ptr}%
\begin{itemdecl}
template<class E, class T, class Y>
  basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const shared_ptr<Y>& p);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
As if by: \tcode{os <{}< p.get();}

\pnum
\returns
\tcode{os}.
\end{itemdescr}

\rSec3[util.smartptr.weak]{Class template \tcode{weak_ptr}}

\rSec4[util.smartptr.weak.general]{General}

\pnum
\indexlibraryglobal{weak_ptr}%
The \tcode{weak_ptr} class template stores a weak reference to an object
that is already managed by a \tcode{shared_ptr}. To access the object, a
\tcode{weak_ptr} can be converted to a \tcode{shared_ptr} using the member
function \tcode{lock}.

\begin{codeblock}
namespace std {
  template<class T> class weak_ptr {
  public:
    using element_type = remove_extent_t<T>;

    // \ref{util.smartptr.weak.const}, constructors
    constexpr weak_ptr() noexcept;
    template<class Y>
      constexpr weak_ptr(const shared_ptr<Y>& r) noexcept;
    constexpr weak_ptr(const weak_ptr& r) noexcept;
    template<class Y>
      constexpr weak_ptr(const weak_ptr<Y>& r) noexcept;
    constexpr weak_ptr(weak_ptr&& r) noexcept;
    template<class Y>
      constexpr weak_ptr(weak_ptr<Y>&& r) noexcept;

    // \ref{util.smartptr.weak.dest}, destructor
    constexpr ~weak_ptr();

    // \ref{util.smartptr.weak.assign}, assignment
    constexpr weak_ptr& operator=(const weak_ptr& r) noexcept;
    template<class Y>
      constexpr weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
    template<class Y>
      constexpr weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    constexpr weak_ptr& operator=(weak_ptr&& r) noexcept;
    template<class Y>
      constexpr weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;

    // \ref{util.smartptr.weak.mod}, modifiers
    constexpr void swap(weak_ptr& r) noexcept;
    constexpr void reset() noexcept;

    // \ref{util.smartptr.weak.obs}, observers
    constexpr long use_count() const noexcept;
    constexpr bool expired() const noexcept;
    constexpr 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;
    size_t owner_hash() const noexcept;
    template<class U>
      constexpr bool owner_equal(const shared_ptr<U>& b) const noexcept;
    template<class U>
      constexpr bool owner_equal(const weak_ptr<U>& b) const noexcept;
  };

  template<class T>
    weak_ptr(shared_ptr<T>) -> weak_ptr<T>;
}
\end{codeblock}

\pnum
Specializations of \tcode{weak_ptr} shall be \oldconceptref{CopyConstructible} and
\oldconceptref{CopyAssignable}, allowing their use in standard
containers.  The template parameter \tcode{T} of \tcode{weak_ptr} may be an
incomplete type.

\rSec4[util.smartptr.weak.const]{Constructors}

\indexlibraryctor{weak_ptr}%
\begin{itemdecl}
constexpr weak_ptr() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{weak_ptr} object that stores a null pointer value.

\pnum
\ensures
\tcode{use_count() == 0}.
\end{itemdescr}

\indexlibraryctor{weak_ptr}%
\begin{itemdecl}
constexpr weak_ptr(const weak_ptr& r) noexcept;
template<class Y> constexpr weak_ptr(const weak_ptr<Y>& r) noexcept;
template<class Y> constexpr weak_ptr(const shared_ptr<Y>& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
For the second and third constructors, \tcode{Y*} is compatible with \tcode{T*}.

\pnum
\effects
If \tcode{r} is empty, constructs
an empty \tcode{weak_ptr} object that stores a null pointer value;
otherwise, constructs
a \tcode{weak_ptr} object that shares ownership
with \tcode{r} and stores a copy of the pointer stored in \tcode{r}.

\pnum
\ensures
\tcode{use_count() == r.use_count()}.
\end{itemdescr}

\indexlibraryctor{weak_ptr}%
\begin{itemdecl}
constexpr weak_ptr(weak_ptr&& r) noexcept;
template<class Y> constexpr weak_ptr(weak_ptr<Y>&& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
For the second constructor, \tcode{Y*} is compatible with \tcode{T*}.

\pnum
\effects
Move constructs a \tcode{weak_ptr} instance from \tcode{r}.

\pnum
\ensures
\tcode{*this} contains the old value of \tcode{r}.
\tcode{r} is empty, stores a null pointer value, and \tcode{r.use_count() == 0}.
\end{itemdescr}

\rSec4[util.smartptr.weak.dest]{Destructor}

\indexlibrarydtor{weak_ptr}%
\begin{itemdecl}
constexpr ~weak_ptr();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Destroys this \tcode{weak_ptr} object but has no
effect on the object its stored pointer points to.
\end{itemdescr}

\rSec4[util.smartptr.weak.assign]{Assignment}

\indexlibrarymember{operator=}{weak_ptr}%
\begin{itemdecl}
constexpr weak_ptr& operator=(const weak_ptr& r) noexcept;
template<class Y> constexpr weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
template<class Y> constexpr weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{weak_ptr(r).swap(*this)}.

\pnum
\returns
\tcode{*this}.

\pnum
\remarks
The implementation may meet the effects (and the
implied guarantees) via different means, without creating a temporary object.
\end{itemdescr}

\indexlibrarymember{operator=}{weak_ptr}%
\begin{itemdecl}
constexpr weak_ptr& operator=(weak_ptr&& r) noexcept;
template<class Y> constexpr weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{weak_ptr(std::move(r)).swap(*this)}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\rSec4[util.smartptr.weak.mod]{Modifiers}
\indexlibrarymember{swap}{weak_ptr}%
\begin{itemdecl}
constexpr void swap(weak_ptr& r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Exchanges the contents of \tcode{*this} and \tcode{r}.
\end{itemdescr}

\indexlibrarymember{reset}{weak_ptr}%
\begin{itemdecl}
constexpr void reset() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{weak_ptr().swap(*this)}.
\end{itemdescr}

\rSec4[util.smartptr.weak.obs]{Observers}
\indexlibrarymember{use_count}{weak_ptr}%
\begin{itemdecl}
constexpr long use_count() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{0} if \tcode{*this} is empty;
otherwise, the number of \tcode{shared_ptr} instances
that share ownership with \tcode{*this}.
\end{itemdescr}

\indexlibrarymember{expired}{weak_ptr}%
\begin{itemdecl}
constexpr bool expired() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{use_count() == 0}.
\end{itemdescr}

\indexlibrarymember{lock}{weak_ptr}%
\begin{itemdecl}
constexpr shared_ptr<T> lock() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{expired() ?\ shared_ptr<T>() :\ shared_ptr<T>(*this)}, executed atomically.
\end{itemdescr}

\indexlibrarymember{owner_before}{weak_ptr}%
\begin{itemdecl}
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;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An unspecified value such that
\begin{itemize}
\item \tcode{owner_before(b)} defines a strict weak ordering as defined in~\ref{alg.sorting};

\item \tcode{!owner_before(b) \&\& !b.owner_before(*this)} is \tcode{true}
if and only if \tcode{owner_equal(b)} is \tcode{true}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{owner_hash}{weak_ptr}%
\begin{itemdecl}
size_t owner_hash() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An unspecified value such that,
for any object \tcode{x} where \tcode{owner_equal(x)} is \tcode{true},
\tcode{owner_hash() == x.owner_hash()} is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{owner_equal}{weak_ptr}%
\begin{itemdecl}
template<class U>
  constexpr bool owner_equal(const shared_ptr<U>& b) const noexcept;
template<class U>
  constexpr bool owner_equal(const weak_ptr<U>& b) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if and only if
\tcode{*this} and \tcode{b} share ownership or are both empty.
Otherwise returns \tcode{false}.

\pnum
\remarks
\tcode{owner_equal} is an equivalence relation.
\end{itemdescr}

\rSec4[util.smartptr.weak.spec]{Specialized algorithms}

\indexlibrarymember{swap}{weak_ptr}%
\begin{itemdecl}
template<class T>
  constexpr void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{a.swap(b)}.
\end{itemdescr}

\rSec3[util.smartptr.ownerless]{Class template \tcode{owner_less}}

\pnum
The class template \tcode{owner_less} allows ownership-based mixed comparisons of shared
and weak pointers.

\indexlibraryglobal{owner_less}%
\begin{codeblock}
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 = @\unspec@;
  };
}
\end{codeblock}

\indexlibrarymember{operator()}{owner_less}%
\pnum
\tcode{operator()(x, y)} returns \tcode{x.owner_before(y)}.
\begin{note}
Note that
\begin{itemize}
\item \tcode{operator()} defines a strict weak ordering as defined in~\ref{alg.sorting};

\item
\tcode{!operator()(a, b) \&\& !operator()(b, a)} is \tcode{true}
if and only if \tcode{a.owner_equal(b)} is \tcode{true}.
\end{itemize}
\end{note}

\rSec3[util.smartptr.owner.hash]{Struct \tcode{owner_hash}}

\pnum
The class \tcode{owner_hash} provides ownership-based hashing.

\indexlibraryglobal{owner_hash}%
\begin{codeblock}
namespace std {
  struct owner_hash {
    template<class T>
      size_t operator()(const shared_ptr<T>&) const noexcept;

    template<class T>
      size_t operator()(const weak_ptr<T>&) const noexcept;

    using is_transparent = @\unspec@;
  };
}
\end{codeblock}

\indexlibrarymember{operator()}{owner_hash}%
\begin{itemdecl}
template<class T>
  size_t operator()(const shared_ptr<T>& x) const noexcept;
template<class T>
  size_t operator()(const weak_ptr<T>& x) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.owner_hash()}.

\pnum
\begin{note}
For any object \tcode{y} where \tcode{x.owner_equal(y)} is \tcode{true},
\tcode{x.owner_hash() == y.owner_hash()} is \tcode{true}.
\end{note}
\end{itemdescr}

\rSec3[util.smartptr.owner.equal]{Struct \tcode{owner_equal}}

\pnum
The class \tcode{owner_equal} provides
ownership-based mixed equality comparisons of shared and weak pointers.

\indexlibraryglobal{owner_equal}%
\begin{codeblock}
namespace std {
  struct owner_equal {
    template<class T, class U>
      constexpr bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept;
    template<class T, class U>
      constexpr bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept;
    template<class T, class U>
      constexpr bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept;
    template<class T, class U>
      constexpr bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept;

    using is_transparent = @\unspec@;
  };
}
\end{codeblock}

\indexlibrarymember{operator()}{owner_equal}%
\begin{itemdecl}
template<class T, class U>
  constexpr bool operator()(const shared_ptr<T>& x, const shared_ptr<U>& y) const noexcept;
template<class T, class U>
  constexpr bool operator()(const shared_ptr<T>& x, const weak_ptr<U>& y) const noexcept;
template<class T, class U>
  constexpr bool operator()(const weak_ptr<T>& x, const shared_ptr<U>& y) const noexcept;
template<class T, class U>
  constexpr bool operator()(const weak_ptr<T>& x, const weak_ptr<U>& y) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.owner_equal(y)}.

\pnum
\begin{note}
\tcode{x.owner_equal(y)} is \tcode{true}
if and only if \tcode{x} and \tcode{y} share ownership or are both empty.
\end{note}
\end{itemdescr}

\rSec3[util.smartptr.enab]{Class template \tcode{enable_shared_from_this}}

\pnum
\indexlibraryglobal{enable_shared_from_this}%
A class \tcode{T} can inherit from \tcode{enable_shared_from_this<T>}
to inherit the \tcode{shared_from_this} member functions that obtain
a \tcode{shared_ptr} instance pointing to \tcode{*this}.

\pnum
\begin{example}
\begin{codeblock}
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_equal(q));                         // \tcode{p} and \tcode{q} share ownership
}
\end{codeblock}
\end{example}

\begin{codeblock}
namespace std {
  template<class T> class enable_shared_from_this {
  protected:
    constexpr enable_shared_from_this() noexcept;
    constexpr enable_shared_from_this(const enable_shared_from_this&) noexcept;
    constexpr enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept;
    constexpr ~enable_shared_from_this();

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

  private:
    mutable weak_ptr<T> @\exposid{weak-this}@;  // \expos
  };
}
\end{codeblock}

\pnum
The template parameter \tcode{T} of \tcode{enable_shared_from_this}
may be an incomplete type.

\indexlibraryctor{enable_shared_from_this}%
\begin{itemdecl}
constexpr enable_shared_from_this() noexcept;
constexpr enable_shared_from_this(const enable_shared_from_this<T>&) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Value-initializes \exposid{weak-this}.
\end{itemdescr}

\indexlibrarymember{operator=}{enable_shared_from_this}%
\begin{itemdecl}
constexpr enable_shared_from_this<T>& operator=(const enable_shared_from_this<T>&) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{*this}.

\pnum
\begin{note}
\exposid{weak-this} is not changed.
\end{note}
\end{itemdescr}

\indexlibraryglobal{shared_ptr}%
\indexlibrarymember{shared_from_this}{enable_shared_from_this}%
\begin{itemdecl}
constexpr shared_ptr<T>       shared_from_this();
constexpr shared_ptr<T const> shared_from_this() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{shared_ptr<T>(\exposid{weak-this})}.
\end{itemdescr}

\indexlibraryglobal{weak_ptr}%
\indexlibrarymember{weak_from_this}{enable_shared_from_this}%
\begin{itemdecl}
constexpr weak_ptr<T>       weak_from_this() noexcept;
constexpr weak_ptr<T const> weak_from_this() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{weak-this}.
\end{itemdescr}

\rSec2[util.smartptr.hash]{Smart pointer hash support}

\indexlibrarymember{hash}{unique_ptr}%
\begin{itemdecl}
template<class T, class D> struct hash<unique_ptr<T, D>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
Letting \tcode{UP} be \tcode{unique_ptr<T, D>},
the specialization \tcode{hash<UP>} is enabled\iref{unord.hash}
if and only if \tcode{hash<typename UP::pointer>} is enabled.
When enabled, for an object \tcode{p} of type \tcode{UP},
\tcode{hash<UP>()(p)} evaluates to
the same value as \tcode{hash<typename UP::pointer>()(p.get())}.
The member functions are not guaranteed to be \keyword{noexcept}.
\end{itemdescr}

\indexlibrarymember{hash}{shared_ptr}%
\begin{itemdecl}
template<class T> struct hash<shared_ptr<T>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
For an object \tcode{p} of type \tcode{shared_ptr<T>},
\tcode{hash<shared_ptr<T>>()(p)} evaluates to
the same value as \tcode{hash<typename shared_ptr<T>::element_type*>()(p.get())}.
\end{itemdescr}%
\indextext{smart pointers|)}

\rSec2[smartptr.adapt]{Smart pointer adaptors}

\rSec3[out.ptr.t]{Class template \tcode{out_ptr_t}}

\pnum
\tcode{out_ptr_t} is a class template used to adapt types
such as smart pointers\iref{smartptr}
for functions that use output pointer parameters.

\pnum
\begin{example}
\begin{codeblock}
#include <memory>
#include <cstdio>

int fopen_s(std::FILE** f, const char* name, const char* mode);

struct fclose_deleter {
  void operator()(std::FILE* f) const noexcept {
    std::fclose(f);
  }
};

int main(int, char*[]) {
  constexpr const char* file_name = "ow.o";
  std::unique_ptr<std::FILE, fclose_deleter> file_ptr;
  int err = fopen_s(std::out_ptr<std::FILE*>(file_ptr), file_name, "r+b");
  if (err != 0)
    return 1;
  // \tcode{*file_ptr} is valid
  return 0;
}
\end{codeblock}
\tcode{unique_ptr} can be used with \tcode{out_ptr}
to be passed into an output pointer-style function,
without needing to hold onto an intermediate pointer value and
manually delete it on error or failure.
\end{example}

\indexlibraryglobal{out_ptr_t}%
\begin{codeblock}
namespace std {
  template<class Smart, class Pointer, class... Args>
  class out_ptr_t {
  public:
    constexpr explicit out_ptr_t(Smart&, Args...);
    out_ptr_t(const out_ptr_t&) = delete;

    constexpr ~out_ptr_t();

    constexpr operator Pointer*() const noexcept;
    operator void**() const noexcept;

  private:
    Smart& s;                   // \expos
    tuple<Args...> a;           // \expos
    Pointer p;                  // \expos
  };
}
\end{codeblock}

\pnum
\tcode{Pointer} shall meet the \oldconceptref{NullablePointer} requirements.
If \tcode{Smart} is a specialization of \tcode{shared_ptr} and
\tcode{sizeof...(Args) == 0},
the program is ill-formed.
\begin{note}
It is typically a user error to reset a \tcode{shared_ptr}
without specifying a deleter,
as \tcode{shared_ptr} will replace a custom deleter upon usage of \tcode{reset},
as specified in \ref{util.smartptr.shared.mod}.
\end{note}

\pnum
Program-defined specializations of \tcode{out_ptr_t}
that depend on at least one program-defined type
need not meet the requirements for the primary template.

\pnum
Evaluations of the conversion functions
on the same object may conflict\iref{intro.races}.

\indexlibraryctor{out_ptr_t}%
\begin{itemdecl}
constexpr explicit out_ptr_t(Smart& smart, Args... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{s} with \tcode{smart},
\tcode{a} with \tcode{std::forward<Args>(args)...}, and
value-initializes \tcode{p}.
Then, equivalent to:
\begin{itemize}
\item
% pretend to \item that there is real text here, but undo the vertical spacing
\mbox{}\vspace{-\baselineskip}\vspace{-\parskip}
\begin{codeblock}
s.reset();
\end{codeblock}
if the expression \tcode{s.reset()} is well-formed;

\item
otherwise,
\begin{codeblock}
s = Smart();
\end{codeblock}
if \tcode{is_constructible_v<Smart>} is \tcode{true};

\item
otherwise, the program is ill-formed.
\end{itemize}

\pnum
\begin{note}
The constructor is not \tcode{noexcept}
to allow for a variety of non-terminating and safe implementation strategies.
For example, an implementation can allocate
a \tcode{shared_ptr}'s internal node in the constructor and
let implementation-defined exceptions escape safely.
The destructor can then move the allocated control block in directly and
avoid any other exceptions.
\end{note}
\end{itemdescr}

\indexlibrarydtor{out_ptr_t}%
\begin{itemdecl}
constexpr ~out_ptr_t();
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{SP} be
\tcode{\exposid{POINTER_OF_OR}(Smart, Pointer)}\iref{memory.general}.

\pnum
\effects
Equivalent to:
\begin{itemize}
\item
% pretend to \item that there is real text here, but undo the vertical spacing
\mbox{}\vspace{-\baselineskip}\vspace{-\parskip}
\begin{codeblock}
if (p) {
  apply([&](auto&&... args) {
    s.reset(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));
}
\end{codeblock}
if the expression
\tcode{s.reset(static_cast<SP>(p), std::forward<Args>(args)...)}
is well-formed;
\item
otherwise,
\begin{codeblock}
if (p) {
  apply([&](auto&&... args) {
    s = Smart(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));
}
\end{codeblock}
if \tcode{is_constructible_v<Smart, SP, Args...>} is \tcode{true};
\item
otherwise, the program is ill-formed.
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
constexpr operator Pointer*() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{operator void**()} has not been called on \tcode{*this}.

\pnum
\returns
\tcode{addressof(const_cast<Pointer\&>(p))}.
\end{itemdescr}

\begin{itemdecl}
operator void**() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_same_v<Pointer, void*>} is \tcode{false}.

\pnum
\mandates
\tcode{is_pointer_v<Pointer>} is \tcode{true}.

\pnum
\expects
\tcode{operator Pointer*()} has not been called on \tcode{*this}.

\pnum
\returns
A pointer value \tcode{v} such that:
\begin{itemize}
\item
the initial value \tcode{*v} is equivalent to \tcode{static_cast<void*>(p)} and
\item
any modification of \tcode{*v}
that is not followed by a subsequent modification of \tcode{*this}
affects the value of \tcode{p} during the destruction of \tcode{*this},
such that \tcode{static_cast<void*>(p) == *v}.
\end{itemize}

\pnum
\remarks
Accessing \tcode{*v} outside the lifetime of \tcode{*this}
has undefined behavior.

\pnum
\begin{note}
\tcode{reinterpret_cast<void**>(static_cast<Pointer*>(*this))}
can be a viable implementation strategy for some implementations.
\end{note}
\end{itemdescr}

\rSec3[out.ptr]{Function template \tcode{out_ptr}}

\indexlibraryglobal{out_ptr}%
\begin{itemdecl}
template<class Pointer = void, class Smart, class... Args>
  constexpr auto out_ptr(Smart& s, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{P} be \tcode{Pointer}
if \tcode{is_void_v<Pointer>} is \tcode{false},
otherwise \tcode{\exposid{POINTER_OF}(Smart)}.

\pnum
\returns
\tcode{out_ptr_t<Smart, P, Args\&\&...>(s, std::forward<Args>(args)...)}.
\end{itemdescr}

\rSec3[inout.ptr.t]{Class template \tcode{inout_ptr_t}}

\pnum
\tcode{inout_ptr_t} is a class template used to adapt types
such as smart pointers\iref{smartptr}
for functions that use output pointer parameters
whose dereferenced values may first be deleted
before being set to another allocated value.

\pnum
\begin{example}
\begin{codeblock}
#include <memory>

struct star_fish* star_fish_alloc();
int star_fish_populate(struct star_fish** ps, const char* description);

struct star_fish_deleter {
  void operator() (struct star_fish* c) const noexcept;
};

using star_fish_ptr = std::unique_ptr<star_fish, star_fish_deleter>;

int main(int, char*[]) {
  star_fish_ptr peach(star_fish_alloc());
  // ...
  // used, need to re-make
  int err = star_fish_populate(std::inout_ptr(peach), "caring clown-fish liker");
  return err;
}
\end{codeblock}
A \tcode{unique_ptr} can be used with \tcode{inout_ptr}
to be passed into an output pointer-style function.
The original value will be properly deleted
according to the function it is used with and
a new value reset in its place.
\end{example}

\indexlibraryglobal{inout_ptr_t}%
\begin{codeblock}
namespace std {
  template<class Smart, class Pointer, class... Args>
  class inout_ptr_t {
  public:
    constexpr explicit inout_ptr_t(Smart&, Args...);
    inout_ptr_t(const inout_ptr_t&) = delete;

    constexpr ~inout_ptr_t();

    constexpr operator Pointer*() const noexcept;
    operator void**() const noexcept;

  private:
    Smart& s;                   // \expos
    tuple<Args...> a;           // \expos
    Pointer p;                  // \expos
  };
}
\end{codeblock}

\pnum
\tcode{Pointer} shall meet the \oldconceptref{NullablePointer} requirements.
If \tcode{Smart} is a specialization of \tcode{shared_ptr},
the program is ill-formed.
\begin{note}
It is impossible to properly acquire unique ownership of the managed resource
from a \tcode{shared_ptr} given its shared ownership model.
\end{note}

\pnum
Program-defined specializations of \tcode{inout_ptr_t}
that depend on at least one program-defined type
need not meet the requirements for the primary template.

\pnum
Evaluations of the conversion functions on the same object
may conflict\iref{intro.races}.

\indexlibraryctor{inout_ptr_t}%
\begin{itemdecl}
constexpr explicit inout_ptr_t(Smart& smart, Args... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{s} with \tcode{smart},
\tcode{a} with \tcode{std::forward<Args>(args)...}, and
\tcode{p} to either
\begin{itemize}
\item \tcode{smart} if \tcode{is_pointer_v<Smart>} is \tcode{true},
\item otherwise, \tcode{smart.get()}.
\end{itemize}

\pnum
\remarks
An implementation can call \tcode{s.release()}.

\pnum
\begin{note}
The constructor is not \tcode{noexcept}
to allow for a variety of non-terminating and safe implementation strategies.
For example, an intrusive pointer implementation with a control block
can allocate in the constructor and safely fail with an exception.
\end{note}
\end{itemdescr}

\indexlibrarydtor{inout_ptr_t}%
\begin{itemdecl}
constexpr ~inout_ptr_t();
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{SP} be
\tcode{\exposid{POINTER_OF_OR}(Smart, Pointer)}\iref{memory.general}.

\pnum
Let \exposid{release-statement} be \tcode{s.release();}
if an implementation does not call \tcode{s.release()} in the constructor.
Otherwise, it is empty.

\pnum
\effects
Equivalent to:
\begin{itemize}
\item
% pretend to \item that there is real text here, but undo the vertical spacing
\mbox{}\vspace{-\baselineskip}\vspace{-\parskip}
\begin{codeblock}
apply([&](auto&&... args) {
  s = Smart(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));
\end{codeblock}
if \tcode{is_pointer_v<Smart>} is \tcode{true};
\item
otherwise,
\begin{codeblock}
@\exposid{release-statement}@;
if (p) {
  apply([&](auto&&... args) {
    s.reset(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));
}
\end{codeblock}
if the expression
\tcode{s.reset(static_cast<SP>(p), std::forward<Args>(args)...)}
is well-\newline formed;
\item
otherwise,
\begin{codeblock}
@\exposid{release-statement}@;
if (p) {
  apply([&](auto&&... args) {
    s = Smart(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a));
}
\end{codeblock}
if \tcode{is_constructible_v<Smart, SP, Args...>} is \tcode{true};
\item
otherwise, the program is ill-formed.
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
constexpr operator Pointer*() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{operator void**()} has not been called on \tcode{*this}.

\pnum
\returns
\tcode{addressof(const_cast<Pointer\&>(p))}.
\end{itemdescr}

\begin{itemdecl}
operator void**() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_same_v<Pointer, void*>} is \tcode{false}.

\pnum
\mandates
\tcode{is_pointer_v<Pointer>} is \tcode{true}.

\pnum
\expects
\tcode{operator Pointer*()} has not been called on \tcode{*this}.

\pnum
\returns
A pointer value \tcode{v} such that:
\begin{itemize}
\item
the initial value \tcode{*v} is equivalent to \tcode{static_cast<void*>(p)} and
\item
any modification of \tcode{*v}
that is not followed by subsequent modification of \tcode{*this}
affects the value of \tcode{p} during the destruction of \tcode{*this},
such that \tcode{static_cast<void*>(p) == *v}.
\end{itemize}

\pnum
\remarks
Accessing \tcode{*v} outside the lifetime of \tcode{*this}
has undefined behavior.

\pnum
\begin{note}
\tcode{reinterpret_cast<void**>(static_cast<Pointer*>(*this))}
can be a viable implementation strategy for some implementations.
\end{note}
\end{itemdescr}

\rSec3[inout.ptr]{Function template \tcode{inout_ptr}}

\indexlibraryglobal{inout_ptr}%
\begin{itemdecl}
template<class Pointer = void, class Smart, class... Args>
  constexpr auto inout_ptr(Smart& s, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{P} be \tcode{Pointer} if \tcode{is_void_v<Pointer>} is \tcode{false},
otherwise \tcode{\exposid{POINTER_OF}(Smart)}.

\pnum
\returns
\tcode{inout_ptr_t<Smart, P, Args\&\&...>(s, std::forward<Args>(args)...)}.
\end{itemdescr}

\rSec1[mem.composite.types]{Types for composite class design}

\rSec2[indirect]{Class template \tcode{indirect}}

\rSec3[indirect.general]{General}

\pnum
An indirect object manages the lifetime of an owned object.
An indirect object is
\defnx{valueless}{valueless!indirect object} if it has no owned object.
An indirect object may become valueless only after it has been moved from.

\pnum
In every specialization \tcode{indirect<T, Allocator>},
if the type \tcode{allocator_traits<Allocator>::value_type}
is not the same type as \tcode{T},
the program is ill-formed.
Every object of type \tcode{indirect<T, Allocator>}
uses an object of type \tcode{Allocator} to allocate and free storage
for the owned object as needed.

\pnum
Constructing an owned object with \tcode{args...}
using the allocator \tcode{a} means calling
\tcode{allocator_traits<Alloca\-tor>::construct(a, \exposid{p}, args...)} where
\tcode{args} is an expression pack,
\tcode{a} is an allocator, and
\exposid{p} is a pointer obtained by
calling \tcode{allocator_traits<Allocator>::allocate}.

\pnum
The member \exposid{alloc} is used for
any memory allocation and element construction
performed by member functions
during the lifetime of each indirect object.
The allocator \exposid{alloc} may be replaced
only via assignment or \tcode{swap()}.
\tcode{Allocator} replacement is performed by
copy assignment,
move assignment, or
swapping of the allocator
only if\iref{container.reqmts}:
\begin{itemize}
\item
\tcode{allocator_traits<Allocator>::propagate_on_container_copy_assignment::value}, or
\item
\tcode{allocator_traits<Allocator>::propagate_on_container_move_assignment::value}, or
\item
\tcode{allocator_traits<Allocator>::propagate_on_container_swap::value}
\end{itemize}
is \tcode{true} within the implementation of
the corresponding \tcode{indirect} operation.

\pnum
A program that instantiates the definition of
the template \tcode{indirect<T, Allocator>} with
a type for the \tcode{T} parameter that is
a non-object type,
an array type,
\tcode{in_place_t},
a specialization of \tcode{in_place_type_t}, or
a cv-qualified type
is ill-formed.

\pnum
The template parameter \tcode{T} of \tcode{indirect}
may be an incomplete type.

\pnum
The template parameter \tcode{Allocator} of \tcode{indirect}
shall meet the \oldconcept{Allocator} requirements.

\pnum
If a program declares an explicit or partial specialization of \tcode{indirect},
the behavior is undefined.

\rSec3[indirect.syn]{Synopsis}

\indexlibraryglobal{indirect}%
\begin{codeblock}
namespace std {
  template<class T, class Allocator = allocator<T>>
  class indirect {
  public:
    using value_type = T;
    using allocator_type = Allocator;
    using pointer = allocator_traits<Allocator>::pointer;
    using const_pointer = allocator_traits<Allocator>::const_pointer;

    // \ref{indirect.ctor}, constructors
    constexpr explicit indirect();
    constexpr explicit indirect(allocator_arg_t, const Allocator& a);
    constexpr indirect(const indirect& other);
    constexpr indirect(allocator_arg_t, const Allocator& a, const indirect& other);
    constexpr indirect(indirect&& other) noexcept;
    constexpr indirect(allocator_arg_t, const Allocator& a, indirect&& other)
      noexcept(@\seebelow@);
    template<class U = T>
      constexpr explicit indirect(U&& u);
    template<class U = T>
      constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u);
    template<class... Us>
      constexpr explicit indirect(in_place_t, Us&&... us);
    template<class... Us>
      constexpr explicit indirect(allocator_arg_t, const Allocator& a,
                                  in_place_t, Us&&... us);
    template<class I, class... Us>
      constexpr explicit indirect(in_place_t, initializer_list<I> ilist, Us&&... us);
    template<class I, class... Us>
      constexpr explicit indirect(allocator_arg_t, const Allocator& a,
                                  in_place_t, initializer_list<I> ilist, Us&&... us);

    // \ref{indirect.dtor}, destructor
    constexpr ~indirect();

    // \ref{indirect.assign}, assignment
    constexpr indirect& operator=(const indirect& other);
    constexpr indirect& operator=(indirect&& other) noexcept(@\seebelow@);
    template<class U = T>
      constexpr indirect& operator=(U&& u);

    // \ref{indirect.obs}, observers
    constexpr const T& operator*() const & noexcept;
    constexpr T& operator*() & noexcept;
    constexpr const T&& operator*() const && noexcept;
    constexpr T&& operator*() && noexcept;
    constexpr const_pointer operator->() const noexcept;
    constexpr pointer operator->() noexcept;
    constexpr bool valueless_after_move() const noexcept;
    constexpr allocator_type get_allocator() const noexcept;

    // \ref{indirect.swap}, swap
    constexpr void swap(indirect& other) noexcept(@\seebelow@);
    friend constexpr void swap(indirect& lhs, indirect& rhs) noexcept(@\seebelow@);

    // \ref{indirect.relops}, relational operators
    template<class U, class AA>
      friend constexpr bool operator==(const indirect& lhs, const indirect<U, AA>& rhs)
        noexcept(@\seebelow@);
    template<class U, class AA>
      friend constexpr auto operator<=>(const indirect& lhs, const indirect<U, AA>& rhs)
        -> @\exposid{synth-three-way-result}@<T, U>;

    // \ref{indirect.comp.with.t}, comparison with \tcode{T}
    template<class U>
      friend constexpr bool operator==(const indirect& lhs, const U& rhs) noexcept(@\seebelow@);
    template<class U>
      friend constexpr auto operator<=>(const indirect& lhs, const U& rhs)
        -> @\exposid{synth-three-way-result}@<T, U>;

  private:
    pointer @\exposid{p}@;                          // \expos
    Allocator @\exposid{alloc}@ = Allocator();      // \expos
  };
  template<class Value>
    indirect(Value) -> indirect<Value>;
  template<class Allocator, class Value>
    indirect(allocator_arg_t, Allocator, Value)
      -> indirect<Value, typename allocator_traits<Allocator>::template rebind_alloc<Value>>;
}
\end{codeblock}

\rSec3[indirect.ctor]{Constructors}

\pnum
The following element applies to all functions in~\ref{indirect.ctor}:

\begin{itemdescr}
\pnum
\throws
Nothing unless \tcode{allocator_traits<Allocator>::allocate} or
\tcode{allocator_traits<Alloca\-tor>::construct} throws.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
constexpr explicit indirect();
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_default_constructible_v<Allocator>} is \tcode{true}.

\pnum
\mandates
\tcode{is_default_constructible_v<T>} is \tcode{true}.

\pnum
\effects
Constructs an owned object of type \tcode{T} with an empty argument list,
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
constexpr explicit indirect(allocator_arg_t, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_default_constructible_v<T>} is \tcode{true}.

\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
Constructs an owned object of type \tcode{T} with an empty argument list,
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
constexpr indirect(const indirect& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_copy_constructible_v<T>} is \tcode{true}.

\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with
\tcode{allocator_traits<Allocator>::select_on_contai\-ner_copy_construction(other.\exposid{alloc})}.
If \tcode{other} is valueless, \tcode{*this} is valueless.
Otherwise,
constructs an owned object of type \tcode{T} with \tcode{*other},
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
constexpr indirect(allocator_arg_t, const Allocator& a, const indirect& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_copy_constructible_v<T>} is \tcode{true}.

\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
If \tcode{other} is valueless, \tcode{*this} is valueless.
Otherwise,
constructs an owned object of type \tcode{T} with \tcode{*other},
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
constexpr indirect(indirect&& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\exposid{alloc} is direct-non-list-initialized from
\tcode{std::move(other.\exposid{alloc})}.
If \tcode{other} is valueless, \tcode{*this} is valueless.
Otherwise \tcode{*this} takes ownership of the owned object of \tcode{other}.

\pnum
\ensures
\tcode{other} is valueless.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
constexpr indirect(allocator_arg_t, const Allocator& a, indirect&& other)
  noexcept(allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
If \tcode{allocator_traits<Allocator>::is_always_equal::value} is \tcode{false}
then \tcode{T} is a complete type.

\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
If \tcode{other} is valueless, \tcode{*this} is valueless.
Otherwise,
if \tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true},
constructs an object of type \tcode{indirect} that
takes ownership of the owned object of \tcode{other}.
Otherwise,
constructs an owned object of type \tcode{T} with \tcode{*std::move(other)},
using the allocator \exposid{alloc}.

\pnum
\ensures
\tcode{other} is valueless.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
template<class U = T>
  constexpr explicit indirect(U&& u);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_same_v<remove_cvref_t<U>, indirect>} is \tcode{false},
\item
\tcode{is_same_v<remove_cvref_t<U>, in_place_t>} is \tcode{false},
\item
\tcode{is_constructible_v<T, U>} is \tcode{true}, and
\item
\tcode{is_default_constructible_v<Allocator>} is \tcode{true}.
\end{itemize}

\pnum
\effects
Constructs an owned object of type \tcode{T} with \tcode{std::forward<U>(u)},
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
template<class U = T>
  constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_same_v<remove_cvref_t<U>, indirect>} is \tcode{false},
\item
\tcode{is_same_v<remove_cvref_t<U>, in_place_t>} is \tcode{false}, and
\item
\tcode{is_constructible_v<T, U>} is \tcode{true}.
\end{itemize}

\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
Constructs an owned object of type \tcode{T} with
\tcode{std::forward<U>(u)},
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
template<class... Us>
  constexpr explicit indirect(in_place_t, Us&&... us);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_constructible_v<T, Us...>} is \tcode{true}, and
\item
\tcode{is_default_constructible_v<Allocator>} is \tcode{true}.
\end{itemize}

\pnum
\effects
Constructs an owned object of type \tcode{T} with
\tcode{std::forward<Us>(us)...},
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
template<class... Us>
  constexpr explicit indirect(allocator_arg_t, const Allocator& a,
                              in_place_t, Us&& ...us);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<T, Us...>} is \tcode{true}.

\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
Constructs an owned object of type \tcode{T} with
\tcode{std::forward<Us>(us)...},
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
template<class I, class... Us>
  constexpr explicit indirect(in_place_t, initializer_list<I> ilist, Us&&... us);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_constructible_v<T, initializer_list<I>\&, Us...>} is \tcode{true}, and
\item
\tcode{is_default_constructible_v<Allocator>} is \tcode{true}.
\end{itemize}

\pnum
\effects
Constructs an owned object of type \tcode{T} with the arguments
\tcode{ilist, std::forward<Us>(us)...},
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{indirect}%
\begin{itemdecl}
template<class I, class... Us>
  constexpr explicit indirect(allocator_arg_t, const Allocator& a,
                              in_place_t, initializer_list<I> ilist, Us&&... us);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<T, initializer_list<I>\&, Us...>} is \tcode{true}.

\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
Constructs an owned object of type \tcode{T} with the arguments
\tcode{ilist, std::forward<Us>(us)...},
using the allocator \exposid{alloc}.
\end{itemdescr}

\rSec3[indirect.dtor]{Destructor}

\indexlibrarydtor{indirect}%
\begin{itemdecl}
constexpr ~indirect();
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{T} is a complete type.

\pnum
\effects
If \tcode{*this} is not valueless,
destroys the owned object
using \tcode{allocator_traits<Allocator>::de\-stroy} and
then the storage is deallocated.
\end{itemdescr}

\rSec3[indirect.assign]{Assignment}

\indexlibrarymember{operator=}{indirect}%
\begin{itemdecl}
constexpr indirect& operator=(const indirect& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates

\begin{itemize}
\item
\tcode{is_copy_assignable_v<T>} is \tcode{true}, and
\item
\tcode{is_copy_constructible_v<T>} is \tcode{true}.
\end{itemize}

\pnum
\effects
If \tcode{addressof(other) == this} is \tcode{true}, there are no effects.
Otherwise:

\begin{itemize}
\item
%FIXME: We're defining what it means for an allocator to "need updating" here?
%FIXME: (Note: that this concept is used elsewhere so it must be defined)...
%FIXME: How is this an "effect"?
The allocator needs updating if
\tcode{allocator_traits<Allocator>::propagate_on_container_copy_assignment::value}
is \tcode{true}.

\item
If \tcode{other} is valueless,
\tcode{*this} becomes valueless and
the owned object in \tcode{*this}, if any,
is destroyed using \tcode{allocator_traits<Allocator>::destroy} and
then the storage is deallocated.

\item
Otherwise,
if \tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true} and
\tcode{*this} is not valueless,
equivalent to \tcode{**this = *other}.

\item
Otherwise a new owned object is constructed in \tcode{*this}
using \tcode{allocator_traits<Allocator>::con\linebreak{}struct} with
the owned object from \tcode{other} as the argument,
using either the allocator in \tcode{*this} or
%FIXME: Concept "allocator needs updating" not defined/referenced.
%FIXME: Same for all usages below.
the allocator in \tcode{other} if the allocator needs updating.

\item
The previously owned object in \tcode{*this}, if any,
is destroyed using \tcode{allocator_traits<Allocator>::\linebreak{}destroy} and
then the storage is deallocated.

\item
If the allocator needs updating,
the allocator in \tcode{*this} is replaced with
a copy of the allocator in \tcode{other}.
\end{itemize}

\pnum
\returns
A reference to \tcode{*this}.

\pnum
\remarks
If any exception is thrown,
the result of the expression \tcode{this->valueless_after_move()}
remains unchanged.
If an exception is thrown during
the call to \tcode{T}{'s} selected copy constructor, no effect.
If an exception is thrown during the call to \tcode{T}{'s} copy assignment,
the state of its owned object
is as defined by the exception safety guarantee of
\tcode{T}{'s} copy assignment.
\end{itemdescr}

\indexlibrarymember{operator=}{indirect}%
\begin{itemdecl}
constexpr indirect& operator=(indirect&& other)
  noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
           allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
If
\tcode{allocator_traits<Allocator>::propagate_on_container_move_assignment::val\-ue}
is \tcode{false} and
\tcode{allocator_traits<Allocator>::is_always_equal::value} is \tcode{false},
\tcode{is_move_con\-structible_v<T>} is \tcode{true}.

\pnum
\effects
If \tcode{addressof(other) == this} is \tcode{true}, there are no effects.
Otherwise:

\begin{itemize}
\item
%FIXME: We're defining "allocator needs updating" as an effect?
%FIXME: (Same issue as above)
The allocator needs updating if
\tcode{allocator_traits<Allocator>::propagate_on_container_move_assignment::value}
is \tcode{true}.

\item
If \tcode{other} is valueless,
\tcode{*this} becomes valueless.

\item
Otherwise,
if the allocator needs updating or
if \tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true},
\tcode{*this} takes ownership of the owned object of \tcode{other}.

\item
Otherwise,
constructs a new owned object with
%FIXME: "as the argument as an rvalue" is awkward.
the owned object of \tcode{other} as the argument as an rvalue,
using the allocator in \tcode{*this}.

\item
The previously owned object in \tcode{*this}, if any,
is destroyed using \tcode{allocator_traits<Allocator>::\linebreak{}destroy} and
then the storage is deallocated.

\item
If the allocator needs updating,
the allocator in \tcode{*this} is replaced with
a copy of the allocator in \tcode{other}.
\end{itemize}

\pnum
\ensures
\tcode{other} is valueless.

\pnum
\returns
A reference to \tcode{*this}.

\pnum
\remarks
If any exception is thrown,
there are no effects on \tcode{*this} or \tcode{other}.
\end{itemdescr}

\indexlibrarymember{operator=}{indirect}%
\begin{itemdecl}
template<class U = T>
  constexpr indirect& operator=(U&& u);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_same_v<remove_cvref_t<U>, indirect>} is \tcode{false},
\item
\tcode{is_constructible_v<T, U>} is \tcode{true}, and
\item
\tcode{is_assignable_v<T\&, U>} is \tcode{true}.
\end{itemize}

\pnum
\effects
If \tcode{*this} is valueless then
constructs an owned object of type \tcode{T} with \tcode{std::forward<U>(u)}
using the allocator \exposid{alloc}.
Otherwise,
equivalent to \tcode{**this = std::forward<U>(u)}.

\pnum
\returns
A reference to \tcode{*this}.
\end{itemdescr}

\rSec3[indirect.obs]{Observers}

\indexlibrarymember{operator*}{indirect}%
\begin{itemdecl}
constexpr const T& operator*() const & noexcept;
constexpr T& operator*() & noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{*this} is not valueless.

\pnum
\returns
\tcode{*\exposid{p}}.
\end{itemdescr}

\indexlibrarymember{operator*}{indirect}%
\begin{itemdecl}
constexpr const T&& operator*() const && noexcept;
constexpr T&& operator*() && noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{*this} is not valueless.

\pnum
\returns
\tcode{std::move(*\exposid{p})}.
\end{itemdescr}

\indexlibrarymember{operator->}{indirect}%
\begin{itemdecl}
constexpr const_pointer operator->() const noexcept;
constexpr pointer operator->() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{*this} is not valueless.

\pnum
\returns
\exposid{p}.
\end{itemdescr}

\indexlibrarymember{valueless_after_move}{indirect}%
\begin{itemdecl}
constexpr bool valueless_after_move() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if \tcode{*this} is valueless, otherwise \tcode{false}.
\end{itemdescr}

\indexlibrarymember{get_allocator}{indirect}%
\begin{itemdecl}
constexpr allocator_type get_allocator() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{alloc}.
\end{itemdescr}

\rSec3[indirect.swap]{Swap}

\indexlibrarymember{swap}{indirect}%
\begin{itemdecl}
constexpr void swap(indirect& other)
  noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
           allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
If
\tcode{allocator_traits<Allocator>::propagate_on_container_swap::value}
is \tcode{true}, then
\tcode{Allocator} meets the \oldconcept{Swappable} requirements.
Otherwise \tcode{get_allocator() == other.\linebreak{}get_allocator()} is \tcode{true}.

\pnum
\effects
Swaps the states of \tcode{*this} and \tcode{other},
exchanging owned objects or valueless states.
If \tcode{allocator_traits<Allocator>::propagate_on_container_swap::value}
is \tcode{true},
then the allocators of \tcode{*this} and \tcode{other}
are exchanged by calling \tcode{swap} as described in~\ref{swappable.requirements}.
Otherwise,
the allocators are not swapped.
\begin{note}
Does not call \tcode{swap} on the owned objects directly.
\end{note}
\end{itemdescr}

\indexlibrarymember{swap}{indirect}%
%FIXME: "friend" included on declaration in synopsis but not here.
\begin{itemdecl}
constexpr void swap(indirect& lhs, indirect& rhs) noexcept(noexcept(lhs.swap(rhs)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{lhs.swap(rhs)}.
\end{itemdescr}

\rSec3[indirect.relops]{Relational operators}

\indexlibrarymember{operator==}{indirect}%
%FIXME: "friend" included on declaration in synopsis but not here.
\begin{itemdecl}
template<class U, class AA>
  constexpr bool operator==(const indirect& lhs, const indirect<U, AA>& rhs)
    noexcept(noexcept(bool(*lhs == *rhs)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The expression \tcode{*lhs == *rhs} is well-formed and
its result is convertible to \tcode{bool}.

\pnum
\returns
If \tcode{lhs} is valueless or \tcode{rhs} is valueless,
\tcode{lhs.valueless_after_move() == rhs.valueless_after_move()};
otherwise \tcode{*lhs == *rhs}.
\end{itemdescr}

\indexlibrarymember{\exposid{synth-three-way-result}}{indirect}%
%FIXME: "friend" included on declaration in synopsis but not here.
\begin{itemdecl}
template<class U, class AA>
  constexpr @\exposid{synth-three-way-result}@<T, U>
    operator<=>(const indirect& lhs, const indirect<U, AA>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
If \tcode{lhs} is valueless or \tcode{rhs} is valueless,
\tcode{!lhs.valueless_after_move() <=> !rhs.value\-less_after_move()};
otherwise
\tcode{\exposid{synth-three-way}(*lhs, *rhs)}.
\end{itemdescr}

\rSec3[indirect.comp.with.t]{Comparison with \tcode{T}}

\indexlibrarymember{operator==}{indirect}%
%FIXME: "friend" included on declaration in synopsis but not here.
\begin{itemdecl}
template<class U>
  constexpr bool operator==(const indirect& lhs, const U& rhs)
    noexcept(noexcept(bool(*lhs == rhs)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The expression \tcode{*lhs == rhs} is well-formed and
its result is convertible to \tcode{bool}.

\pnum
\returns
If \tcode{lhs} is valueless, \tcode{false};
otherwise \tcode{*lhs == rhs}.
\end{itemdescr}

\indexlibrarymember{\exposid{synth-three-way-result}}{indirect}%
%FIXME: "friend" included on declaration in synopsis but not here.
\begin{itemdecl}
template<class U>
  constexpr @\exposid{synth-three-way-result}@<T, U>
    operator<=>(const indirect& lhs, const U& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
If \tcode{lhs} is valueless, \tcode{strong_ordering::less};
otherwise \tcode{\exposid{synth-three-way}(*lhs, rhs)}.
\end{itemdescr}

\rSec3[indirect.hash]{Hash support}

\indexlibrarymember{hash}{indirect}%
\begin{itemdecl}
template<class T, class Allocator>
struct hash<indirect<T, Allocator>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
The specialization \tcode{hash<indirect<T, Allocator>>}
is enabled\iref{unord.hash} if and only if \tcode{hash<T>} is enabled.
When enabled for an object \tcode{i} of type \tcode{indirect<T, Allocator>},
%FIXME: Cleanup wording/punctuation and make consistent.
\tcode{hash<indirect<T, Allocator>>()(i)} evaluates to
either the same value as \tcode{hash<T>()(*i)},
if \tcode{i} is not valueless;
otherwise to an
\impldef{result of evaluating \tcode{hash<indirect<T, Allocator>>()(i)} if \tcode{i} is valueless}
value.
The member functions are not guaranteed to be \tcode{noexcept}.
\end{itemdescr}

\rSec2[polymorphic]{Class template \tcode{polymorphic}}

\rSec3[polymorphic.general]{General}

\pnum
A polymorphic object manages the lifetime of an owned object.
A polymorphic object may own objects of
different types at different points in its lifetime.
A polymorphic object is
\defnx{valueless}{valueless!polymorphic object}
if it has no owned object.
A polymorphic object may become valueless only after it has been moved from.

\pnum
In every specialization \tcode{polymorphic<T, Allocator>},
if the type \tcode{allocator_traits<Allocator>::value_type}
is not the same type as \tcode{T}, the program is ill-formed.
Every object of type \tcode{polymorphic<T, Allocator>}
uses an object of type \tcode{Allocator} to
allocate and free storage for the owned object as needed.

\pnum
Constructing an owned object of type \tcode{U} with \tcode{args...}
using the allocator \tcode{a} means calling
\tcode{allocator_traits<Allocator>::construct(a, \exposid{p}, args...)} where
\tcode{args} is an expression pack,
\tcode{a} is an allocator, and
\exposid{p} points to storage suitable for an owned object of type \tcode{U}.

\pnum
The member \exposid{alloc} is used for
any memory allocation and element construction
performed by member functions
during the lifetime of each polymorphic value object, or
until the allocator is replaced.
The allocator may be replaced only via
assignment or \tcode{swap()}.
\tcode{Allocator} replacement is performed by
copy assignment,
move assignment, or
swapping of the allocator
only if\iref{container.reqmts}:
\begin{itemize}
\item
\tcode{allocator_traits<Allocator>::propagate_on_container_copy_assignment::value}, or
\item
\tcode{allocator_traits<Allocator>::propagate_on_container_move_assignment::value}, or
\item
\tcode{allocator_traits<Allocator>::propagate_on_container_swap::value}
\end{itemize}
is \tcode{true} within the implementation of
the corresponding \tcode{polymorphic} operation.

\pnum
A program that instantiates the definition of \tcode{polymorphic} for
a non-object type,
an array type,
\tcode{in_place_t},
a specialization of \tcode{in_place_type_t}, or
a cv-qualified type
is ill-formed.

\pnum
The template parameter \tcode{T} of \tcode{polymorphic}
may be an incomplete type.

\pnum
The template parameter \tcode{Allocator} of \tcode{polymorphic}
shall meet the requirements of \oldconcept{Allocator}.

\pnum
If a program declares an explicit or
partial specialization of \tcode{polymorphic},
the behavior is undefined.

\rSec3[polymorphic.syn]{Synopsis}

\indexlibraryglobal{polymorphic}%
\begin{codeblock}
namespace std {
  template<class T, class Allocator = allocator<T>>
  class polymorphic {
  public:
    using value_type = T;
    using allocator_type = Allocator;
    using pointer = allocator_traits<Allocator>::pointer;
    using const_pointer = allocator_traits<Allocator>::const_pointer;

    // \ref{polymorphic.ctor}, constructors
    constexpr explicit polymorphic();
    constexpr explicit polymorphic(allocator_arg_t, const Allocator& a);
    constexpr polymorphic(const polymorphic& other);
    constexpr polymorphic(allocator_arg_t, const Allocator& a, const polymorphic& other);
    constexpr polymorphic(polymorphic&& other) noexcept;
    constexpr polymorphic(allocator_arg_t, const Allocator& a, polymorphic&& other)
      noexcept(@\seebelow@);
    template<class U = T>
      constexpr explicit polymorphic(U&& u);
    template<class U = T>
      constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, U&& u);
    template<class U, class... Ts>
      constexpr explicit polymorphic(in_place_type_t<U>, Ts&&... ts);
    template<class U, class... Ts>
      constexpr explicit polymorphic(allocator_arg_t, const Allocator& a,
                                     in_place_type_t<U>, Ts&&... ts);
    template<class U, class I, class... Us>
      constexpr explicit polymorphic(in_place_type_t<U>, initializer_list<I> ilist, Us&&... us);
    template<class U, class I, class... Us>
      constexpr explicit polymorphic(allocator_arg_t, const Allocator& a,
                                     in_place_type_t<U>, initializer_list<I> ilist, Us&&... us);

    // \ref{polymorphic.dtor}, destructor
    constexpr ~polymorphic();

    // \ref{polymorphic.assign}, assignment
    constexpr polymorphic& operator=(const polymorphic& other);
    constexpr polymorphic& operator=(polymorphic&& other) noexcept(@\seebelow@);

    // \ref{polymorphic.obs}, observers
    constexpr const T& operator*() const noexcept;
    constexpr T& operator*() noexcept;
    constexpr const_pointer operator->() const noexcept;
    constexpr pointer operator->() noexcept;
    constexpr bool valueless_after_move() const noexcept;
    constexpr allocator_type get_allocator() const noexcept;

    // \ref{polymorphic.swap}, swap
    constexpr void swap(polymorphic& other) noexcept(@\seebelow@);
    friend constexpr void swap(polymorphic& lhs, polymorphic& rhs) noexcept(@\seebelow@);

  private:
    Allocator @\exposid{alloc}@ = Allocator();      // \expos
  };
}
\end{codeblock}

\rSec3[polymorphic.ctor]{Constructors}

\pnum
The following element applies to all functions in~\ref{polymorphic.ctor}:

\begin{itemdescr}
\pnum
\throws
Nothing unless \tcode{allocator_traits<Allocator>::allocate} or
\tcode{allocator_traits<Alloca\-tor>::construct} throws.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
constexpr explicit polymorphic();
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_default_constructible_v<Allocator>} is \tcode{true}.

\pnum
\mandates
\begin{itemize}
\item
\tcode{is_default_constructible_v<T>} is \tcode{true}, and
\item
\tcode{is_copy_constructible_v<T>} is \tcode{true}.
\end{itemize}

\pnum
\effects
Constructs an owned object of type \tcode{T} with an empty argument list
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
constexpr explicit polymorphic(allocator_arg_t, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\begin{itemize}
\item
\tcode{is_default_constructible_v<T>} is \tcode{true}, and
\item
\tcode{is_copy_constructible_v<T>} is \tcode{true}.
\end{itemize}

\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
Constructs an owned object of type \tcode{T} with an empty argument list
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
constexpr polymorphic(const polymorphic& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with
\tcode{allocator_traits<Allocator>::select_on_contai\-ner_copy_construction(other.\exposid{alloc})}.
If \tcode{other} is valueless, \tcode{*this} is valueless.
Otherwise,
constructs an owned object of type \tcode{U}, where
\tcode{U} is the type of the owned object in \tcode{other}, with
the owned object in \tcode{other} using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
constexpr polymorphic(allocator_arg_t, const Allocator& a, const polymorphic& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
If \tcode{other} is valueless, \tcode{*this} is valueless.
Otherwise,
constructs an owned object of type \tcode{U}, where
\tcode{U} is the type of the owned object in \tcode{other}, with
the owned object in \tcode{other} using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
constexpr polymorphic(polymorphic&& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with
\tcode{std::move(other.\exposid{alloc})}.
If \tcode{other} is valueless, \tcode{*this} is valueless.
Otherwise,
either \tcode{*this}
takes ownership of the owned object of \tcode{other} or,
%FIXME: Cleanup awkward wording.
owns an object of the same type
constructed from the owned object of \tcode{other}
considering that owned object as an rvalue,
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
constexpr polymorphic(allocator_arg_t, const Allocator& a, polymorphic&& other)
  noexcept(allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
If \tcode{other} is valueless, \tcode{*this} is valueless.
Otherwise,
if \tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true},
either constructs an object of type \tcode{polymorphic} that
owns the owned object of \tcode{other},
making \tcode{other} valueless; or,
%FIXME: Cleanup awkward wording. (And similar wording elsewhere).
owns an object of the same type constructed from
the owned object of \tcode{other}
considering that owned object as an rvalue.
Otherwise,
if \tcode{\exposid{alloc} != other.\exposid{alloc}} is \tcode{true},
constructs an owned object of type \tcode{U},
where \tcode{U} is the type of the owned object in \tcode{other},
with the owned object in \tcode{other} as an rvalue,
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
template<class U = T>
  constexpr explicit polymorphic(U&& u);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
Where \tcode{UU} is \tcode{remove_cvref_t<U>},
\begin{itemize}
\item
\tcode{is_same_v<UU, polymorphic>} is \tcode{false},
\item
\tcode{derived_from<UU, T>} is \tcode{true},
\item
\tcode{is_constructible_v<UU, U>} is \tcode{true},
\item
\tcode{is_copy_constructible_v<UU>} is \tcode{true},
\item
\tcode{UU} is not a specialization of \tcode{in_place_type_t}, and
\item
\tcode{is_default_constructible_v<Allocator>} is \tcode{true}.
\end{itemize}

\pnum
\effects
Constructs an owned object of type \tcode{UU} with \tcode{std::forward<U>(u)}
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
template<class U = T>
  constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, U&& u);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
Where \tcode{UU} is \tcode{remove_cvref_t<U>},
\begin{itemize}
\item
\tcode{is_same_v<UU, polymorphic>} is \tcode{false},
\item
\tcode{derived_from<UU, T>} is \tcode{true},
\item
\tcode{is_constructible_v<UU, U>} is \tcode{true},
\item
\tcode{is_copy_constructible_v<UU>} is \tcode{true}, and
\item
\tcode{UU} is not a specialization of \tcode{in_place_type_t}.
\end{itemize}

\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
Constructs an owned object of type \tcode{UU} with \tcode{std::forward<U>(u)}
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
template<class U, class... Ts>
  constexpr explicit polymorphic(in_place_type_t<U>, Ts&&... ts);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_same_v<remove_cvref_t<U>, U>} is \tcode{true},
\item
\tcode{derived_from<U, T>} is \tcode{true},
\item
\tcode{is_constructible_v<U, Ts...>} is \tcode{true},
\item
\tcode{is_copy_constructible_v<U>} is \tcode{true}, and
\item
\tcode{is_default_constructible_v<Allocator>} is \tcode{true}.
\end{itemize}

\pnum
\effects
Constructs an owned object of type \tcode{U} with
\tcode{std::forward<Ts>(ts)...}
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
template<class U, class... Ts>
  constexpr explicit polymorphic(allocator_arg_t, const Allocator& a,
                                 in_place_type_t<U>, Ts&&... ts);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_same_v<remove_cvref_t<U>, U>} is \tcode{true},
\item
\tcode{derived_from<U, T>} is \tcode{true},
\item
\tcode{is_constructible_v<U, Ts...>} is \tcode{true}, and
\item
\tcode{is_copy_constructible_v<U>} is \tcode{true}.
\end{itemize}

\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
Constructs an owned object of type \tcode{U} with
\tcode{std::forward<Ts>(ts)...}
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
template<class U, class I, class... Us>
  constexpr explicit polymorphic(in_place_type_t<U>, initializer_list<I> ilist, Us&&... us);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_same_v<remove_cvref_t<U>, U>} is \tcode{true},
\item
\tcode{derived_from<U, T>} is \tcode{true},
\item
\tcode{is_constructible_v<U, initializer_list<I>\&, Us...>} is \tcode{true},
\item
\tcode{is_copy_constructible_v<U>} is \tcode{true}, and
\item
\tcode{is_default_constructible_v<Allocator>} is \tcode{true}.
\end{itemize}

\pnum
\effects
Constructs an owned object of type \tcode{U} with
the arguments \tcode{ilist, std::forward<Us>(us)...}
using the allocator \exposid{alloc}.
\end{itemdescr}

\indexlibraryctor{polymorphic}%
\begin{itemdecl}
template<class U, class I, class... Us>
  constexpr explicit polymorphic(allocator_arg_t, const Allocator& a,
                                 in_place_type_t<U>, initializer_list<I> ilist, Us&&... us);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints

\begin{itemize}
\item
\tcode{is_same_v<remove_cvref_t<U>, U>} is \tcode{true},
\item
\tcode{derived_from<U, T>} is \tcode{true},
\item
\tcode{is_constructible_v<U, initializer_list<I>\&, Us...>} is \tcode{true}, and
\item
\tcode{is_copy_constructible_v<U>} is \tcode{true}.
\end{itemize}

\pnum
\effects
\exposid{alloc} is direct-non-list-initialized with \tcode{a}.
Constructs an owned object of type \tcode{U} with the arguments
\tcode{ilist, std::forward<Us>(us)...}
using the allocator \exposid{alloc}.
\end{itemdescr}

\rSec3[polymorphic.dtor]{Destructor}

\indexlibrarydtor{polymorphic}%
\begin{itemdecl}
constexpr ~polymorphic();
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{T} is a complete type.

\pnum
\effects
If \tcode{*this} is not valueless,
calls \tcode{allocator_traits<Allocator>::destroy(p)},
where \tcode{p} is a pointer of type \tcode{U*} to
the owned object and
\tcode{U} is the type of the owned object;
then the storage is deallocated.
\end{itemdescr}

\rSec3[polymorphic.assign]{Assignment}

\indexlibrarymember{operator=}{polymorphic}%
\indexlibrarydtor{polymorphic}%
\begin{itemdecl}
constexpr polymorphic& operator=(const polymorphic& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{T} is a complete type.

\pnum
\effects
If \tcode{addressof(other) == this} is \tcode{true}, there are no effects.
Otherwise:

\begin{itemize}
\item
%FIXME: We're defining "allocator needs updating" as an effect?
%FIXME: (Same issue as above)
The allocator needs updating if
\tcode{allocator_traits<Allocator>::propagate_on_contai\-ner_copy_assignment::value}
is \tcode{true}.

\item
If \tcode{other} is not valueless,
a new owned object of type \tcode{U},
where \tcode{U} is the type of the owned object in \tcode{other},
is constructed in \tcode{*this} using
\tcode{allocator_traits<Allocator>::construct} with
the owned object from \tcode{other} as the argument, using either
the allocator in \tcode{*this} or
the allocator in \tcode{other} if the allocator needs updating.

\item
The previously owned object in \tcode{*this}, if any,
is destroyed using \tcode{allocator_traits<Allocator>::\linebreak{}destroy} and
then the storage is deallocated.

\item
If the allocator needs updating,
the allocator in \tcode{*this} is replaced with
a copy of the allocator in \tcode{other}.
\end{itemize}

\pnum
\returns
A reference to \tcode{*this}.

\pnum
\remarks
If any exception is thrown, there are no effects on \tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator=}{polymorphic}%
\begin{itemdecl}
constexpr polymorphic& operator=(polymorphic&& other)
  noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
           allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
If
\tcode{allocator_traits<Allocator>::propagate_on_container_move_assignment::val\-ue}
is \tcode{false} and
\tcode{allocator_traits<Allocator>::is_always_equal::value} is \tcode{false},
\tcode{T} is a complete type.

\pnum
\effects
If \tcode{addressof(other) == this} is \tcode{true}, there are no effects.
Otherwise:

\begin{itemize}
\item
%FIXME: We're defining "allocator needs updating" as an effect?
%FIXME: (Same issue as above)
The allocator needs updating if
\tcode{allocator_traits<Allocator>::propagate_on_container_move_assignment::value}
is \tcode{true}.

\item
If \tcode{other} is valueless, \tcode{*this} becomes valueless.

\item
Otherwise,
if the allocator needs updating or
\tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true},
\tcode{*this} takes ownership of the owned object of \tcode{other}.

\item
Otherwise,
constructs a new owned object of type \tcode{U},
where \tcode{U} is the type of the owned object in \tcode{other},
with the owned object of
\tcode{other} as the argument as an rvalue,
using the allocator in \tcode{*this}.

\item
The previously owned object in \tcode{*this}, if any,
is destroyed using \tcode{allocator_traits<Allocator>::\linebreak{}destroy} and
then the storage is deallocated.

\item
If the allocator needs updating,
the allocator in \tcode{*this} is replaced with
a copy of the allocator in \tcode{other}.
\end{itemize}

\pnum
\returns
A reference to \tcode{*this}.

\pnum
\remarks
If any exception is thrown,
there are no effects on \tcode{*this} or \tcode{other}.
\end{itemdescr}

\rSec3[polymorphic.obs]{Observers}

\indexlibrarymember{operator*}{polymorphic}%
\begin{itemdecl}
constexpr const T& operator*() const noexcept;
constexpr T& operator*() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{*this} is not valueless.

\pnum
\returns
A reference to the owned object.
\end{itemdescr}

\indexlibrarymember{operator->}{polymorphic}%
\begin{itemdecl}
constexpr const_pointer operator->() const noexcept;
constexpr pointer operator->() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{*this} is not valueless.

\pnum
\returns
A pointer to the owned object.
\end{itemdescr}

\indexlibrarymember{valueless_after_move}{polymorphic}%
\begin{itemdecl}
constexpr bool valueless_after_move() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if \tcode{*this} is valueless, otherwise \tcode{false}.
\end{itemdescr}

\indexlibrarymember{get_allocator}{polymorphic}%
\begin{itemdecl}
constexpr allocator_type get_allocator() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{alloc}.
\end{itemdescr}

\rSec3[polymorphic.swap]{Swap}

\indexlibrarymember{swap}{polymorphic}%
\begin{itemdecl}
constexpr void swap(polymorphic& other)
  noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
           allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
If \tcode{allocator_traits<Allocator>::propagate_on_container_swap::value}
is \tcode{true}, then
\tcode{Allocator} meets the \oldconcept{Swappable} requirements.
Otherwise \tcode{get_allocator() == other.\linebreak{}get_allocator()} is \tcode{true}.

\pnum
\effects
Swaps the states of \tcode{*this} and \tcode{other},
exchanging owned objects or valueless states.
If \tcode{allocator_traits<Allocator>::propagate_on_container_swap::value}
is \tcode{true}, then
the allocators of \tcode{*this} and \tcode{other}
are exchanged by calling \tcode{swap}
as described in~\ref{swappable.requirements}.
Otherwise,
the allocators are not swapped.
\begin{note}
Does not call \tcode{swap} on the owned objects directly.
\end{note}
\end{itemdescr}

\indexlibrarymember{swap}{polymorphic}%
%FIXME: "friend" included on declaration in synopsis but not here.
\begin{itemdecl}
constexpr void swap(polymorphic& lhs, polymorphic& rhs) noexcept(noexcept(lhs.swap(rhs)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{lhs.swap(rhs)}.
\end{itemdescr}

\rSec1[mem.res]{Memory resources}

\rSec2[mem.res.syn]{Header \tcode{<memory_resource>} synopsis}

\indexheader{memory_resource}%
\begin{codeblock}
namespace std::pmr {
  // \ref{mem.res.class}, class \tcode{memory_resource}
  class memory_resource;

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

  // \ref{mem.poly.allocator.class}, class template \tcode{polymorphic_allocator}
  template<class Tp = byte> class polymorphic_allocator;

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

  // \ref{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;

  // \ref{mem.res.pool}, pool resource classes
  struct pool_options;
  class synchronized_pool_resource;
  class unsynchronized_pool_resource;
  class monotonic_buffer_resource;
}
\end{codeblock}

\rSec2[mem.res.class]{Class \tcode{memory_resource}}

\rSec3[mem.res.class.general]{General}

\pnum
The \tcode{memory_resource} class is an abstract interface to an unbounded set of classes encapsulating memory resources.

\indexlibraryglobal{memory_resource}%
\indexlibrarymember{operator=}{memory_resource}%
\begin{codeblock}
namespace std::pmr {
  class memory_resource {
    static constexpr size_t max_align = alignof(max_align_t);   // \expos

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

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

    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;
  };
}
\end{codeblock}


\rSec3[mem.res.public]{Public member functions}

\indexlibrarydtor{memory_resource}%
\begin{itemdecl}
~memory_resource();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Destroys this \tcode{memory_resource}.
\end{itemdescr}

\indexlibrarymember{allocate}{memory_resource}%
\begin{itemdecl}
void* allocate(size_t bytes, size_t alignment = max_align);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Allocates storage by calling \tcode{do_allocate(bytes, alignment)} and
implicitly creates objects within the allocated region of storage.

\pnum
\returns
A pointer to a suitable created object\iref{intro.object}
in the allocated region of storage.

\pnum
\throws
What and when the call to \tcode{do_allocate} throws.
\end{itemdescr}

\indexlibrarymember{deallocate}{memory_resource}%
\begin{itemdecl}
void deallocate(void* p, size_t bytes, size_t alignment = max_align);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{do_deallocate(p, bytes, alignment)}.
\end{itemdescr}

\indexlibrarymember{is_equal}{memory_resource}%
\begin{itemdecl}
bool is_equal(const memory_resource& other) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return do_is_equal(other);}
\end{itemdescr}


\rSec3[mem.res.private]{Private virtual member functions}

\indexlibrarymember{do_allocate}{memory_resource}%
\begin{itemdecl}
virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{alignment} is a power of two.

\pnum
\returns
A derived class shall implement this function to
return a pointer to allocated storage\iref{basic.stc.dynamic.allocation}
with a size of at least \tcode{bytes},
aligned to the specified \tcode{alignment}.

\pnum
\throws
A derived class implementation shall throw an appropriate exception if it is unable to allocate memory with the requested size and alignment.
\end{itemdescr}

\indexlibrarymember{do_deallocate}{memory_resource}%
\begin{itemdecl}
virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{p} was returned from a prior call to \tcode{allocate(bytes, alignment)}
on a memory resource equal to \tcode{*this},
and the storage at \tcode{p} has not yet been deallocated.

\pnum
\effects
A derived class shall implement this function to dispose of allocated storage.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{do_is_equal}{memory_resource}%
\begin{itemdecl}
virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A derived class shall implement this function to return \tcode{true} if memory allocated from \tcode{*this} can be deallocated from \tcode{other} and vice-versa,
otherwise \tcode{false}.
\begin{note}
It is possible that the most-derived type of \tcode{other} does not match the type of \tcode{*this}.
For a derived class \tcode{D}, an implementation of this function
can immediately return \tcode{false}
if \tcode{dynamic_cast<const D*>(\&other) == nullptr}.
\end{note}
\end{itemdescr}

\rSec3[mem.res.eq]{Equality}

\indexlibrarymember{operator==}{memory_resource}%
\begin{itemdecl}
bool operator==(const memory_resource& a, const memory_resource& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\&a == \&b || a.is_equal(b)}.
\end{itemdescr}

\rSec2[mem.poly.allocator.class]{Class template \tcode{polymorphic_allocator}}

\rSec3[mem.poly.allocator.class.general]{General}

\pnum
A specialization of class template \tcode{pmr::polymorphic_allocator} meets
the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}
if its template argument is a \cv-unqualified object type.
Constructed with different memory resources,
different instances of the same specialization of \tcode{pmr::polymorphic_allocator}
can exhibit entirely different allocation behavior.
This runtime polymorphism allows objects that use \tcode{polymorphic_allocator}
to behave as if they used different allocator types at run time
even though they use the same static allocator type.

\pnum
A specialization of class template \tcode{pmr::polymorphic_allocator}
meets the allocator completeness requirements\iref{allocator.requirements.completeness}
if its template argument is a \cv-unqualified object type.

\indexlibraryglobal{polymorphic_allocator}%
\indexlibrarymember{value_type}{polymorphic_allocator}%
\begin{codeblock}
namespace std::pmr {
  template<class Tp = byte> class polymorphic_allocator {
    memory_resource* memory_rsrc;       // \expos

  public:
    using value_type = Tp;

    // \ref{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;

    // \ref{mem.poly.allocator.mem}, member functions
    Tp* allocate(size_t n);
    void deallocate(Tp* p, size_t n);

    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> T* allocate_object(size_t n = 1);
    template<class T> void deallocate_object(T* p, size_t n = 1);
    template<class T, class... CtorArgs> 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;

    // friends
    friend bool operator==(const polymorphic_allocator& a,
                           const polymorphic_allocator& b) noexcept {
      return *a.resource() == *b.resource();
    }
  };
}
\end{codeblock}

\rSec3[mem.poly.allocator.ctor]{Constructors}

\indexlibraryctor{polymorphic_allocator}%
\begin{itemdecl}
polymorphic_allocator() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Sets \tcode{memory_rsrc} to \tcode{get_default_resource()}.
\end{itemdescr}

\indexlibraryctor{polymorphic_allocator}%
\begin{itemdecl}
polymorphic_allocator(memory_resource* r);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{r} is non-null.

\pnum
\effects
Sets \tcode{memory_rsrc} to \tcode{r}.

\pnum
\throws
Nothing.

\pnum
\begin{note}
This constructor provides an implicit conversion from \tcode{memory_resource*}.
\end{note}
\end{itemdescr}

\indexlibraryctor{polymorphic_allocator}%
\begin{itemdecl}
template<class U> polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Sets \tcode{memory_rsrc} to \tcode{other.resource()}.
\end{itemdescr}


\rSec3[mem.poly.allocator.mem]{Member functions}

\indexlibrarymember{allocate}{polymorphic_allocator}%
\begin{itemdecl}
Tp* allocate(size_t n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
If \tcode{numeric_limits<size_t>::max() / sizeof(Tp) < n},
throws \tcode{bad_array_new_length}.
Otherwise equivalent to:
\begin{codeblock}
return static_cast<Tp*>(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp)));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{deallocate}{polymorphic_allocator}%
\begin{itemdecl}
void deallocate(Tp* p, size_t n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{p} was allocated from a memory resource \tcode{x},
equal to \tcode{*memory_rsrc},
using \tcode{x.allocate(n * sizeof(Tp), alignof(Tp))}.

\pnum
\effects
Equivalent to \tcode{memory_rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp))}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{allocate_bytes}{polymorphic_allocator}%
\begin{itemdecl}
void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return memory_rsrc->allocate(nbytes, alignment);}

\pnum
\begin{note}
The return type is \tcode{void*} (rather than, e.g., \tcode{byte*})
to support conversion to an arbitrary pointer type \tcode{U*}
by \tcode{static_cast<U*>}, thus facilitating construction of a \tcode{U}
object in the allocated memory.
\end{note}
\end{itemdescr}

\indexlibrarymember{deallocate_bytes}{polymorphic_allocator}%
\begin{itemdecl}
void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{memory_rsrc->deallocate(p, nbytes, alignment)}.
\end{itemdescr}

\indexlibrarymember{allocate_object}{polymorphic_allocator}%
\begin{itemdecl}
template<class T>
  T* allocate_object(size_t n = 1);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Allocates memory suitable for holding
an array of \tcode{n} objects of type \tcode{T}, as follows:
\begin{itemize}
\item
  if \tcode{numeric_limits<size_t>::max() / sizeof(T) < n},
  throws \tcode{bad_array_new_length},
\item
  otherwise equivalent to:
\begin{codeblock}
return static_cast<T*>(allocate_bytes(n*sizeof(T), alignof(T)));
\end{codeblock}
\end{itemize}

\pnum
\begin{note}
\tcode{T} is not deduced and must therefore be provided as a template argument.
\end{note}
\end{itemdescr}

\indexlibrarymember{deallocate_object}{polymorphic_allocator}%
\begin{itemdecl}
template<class T>
  void deallocate_object(T* p, size_t n = 1);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{deallocate_bytes(p, n*sizeof(T), alignof(T))}.
\end{itemdescr}

\indexlibrarymember{new_object}{polymorphic_allocator}%
\begin{itemdecl}
template<class T, class... CtorArgs>
  T* new_object(CtorArgs&&... ctor_args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Allocates and constructs an object of type \tcode{T}, as follows.\newline
Equivalent to:
\begin{codeblock}
T* p = allocate_object<T>();
try {
  construct(p, std::forward<CtorArgs>(ctor_args)...);
} catch (...) {
  deallocate_object(p);
  throw;
}
return p;
\end{codeblock}

\pnum
\begin{note}
\tcode{T} is not deduced and must therefore be provided as a template argument.
\end{note}
\end{itemdescr}

\indexlibrarymember{new_object}{polymorphic_allocator}%
\begin{itemdecl}
template<class T>
  void delete_object(T* p);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
destroy(p);
deallocate_object(p);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{construct}{polymorphic_allocator}%
\begin{itemdecl}
template<class T, class... Args>
  void construct(T* p, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
Uses-allocator construction of \tcode{T}
with allocator \tcode{*this} (see~\ref{allocator.uses.construction})
and constructor arguments \tcode{std::forward<Args>(args)...} is well-formed.

\pnum
\effects
Constructs a \tcode{T} object in the storage
whose address is represented by \tcode{p}
by uses-allocator construction with allocator \tcode{*this}
and constructor arguments \tcode{std::forward<Args>(args)...}.

\pnum
\throws
Nothing unless the constructor for \tcode{T} throws.
\end{itemdescr}

\indexlibrarymember{destroy}{polymorphic_allocator}%
\begin{itemdecl}
template<class T>
  void destroy(T* p);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{p->\~T()}.
\end{itemdescr}

\indexlibrarymember{select_on_container_copy_construction}{polymorphic_allocator}%
\begin{itemdecl}
polymorphic_allocator select_on_container_copy_construction() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{polymorphic_allocator()}.

\pnum
\begin{note}
The memory resource is not propagated.
\end{note}
\end{itemdescr}

\indexlibrarymember{resource}{polymorphic_allocator}%
\begin{itemdecl}
memory_resource* resource() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{memory_rsrc}.
\end{itemdescr}

\rSec3[mem.poly.allocator.eq]{Equality}

\indexlibrarymember{operator==}{polymorphic_allocator}%
\begin{itemdecl}
template<class T1, class T2>
  bool operator==(const polymorphic_allocator<T1>& a,
                  const polymorphic_allocator<T2>& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{*a.resource() == *b.resource()}.
\end{itemdescr}

\rSec2[mem.res.global]{Access to program-wide \tcode{memory_resource} objects}

\indexlibraryglobal{new_delete_resource}%
\begin{itemdecl}
memory_resource* new_delete_resource() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A pointer to a static-duration object of a type derived from \tcode{memory_resource}
that can serve as a resource for allocating memory
using \tcode{::operator new} and \tcode{::operator delete}.
The same value is returned every time this function is called.
For a return value \tcode{p} and a memory resource \tcode{r},
\tcode{p->is_equal(r)} returns \tcode{\&r == p}.
\end{itemdescr}

\indexlibraryglobal{null_memory_resource}%
\begin{itemdecl}
memory_resource* null_memory_resource() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A pointer to a static-duration object of a type derived from \tcode{memory_resource}
for which \tcode{allocate()} always throws \tcode{bad_alloc} and
for which \tcode{deallocate()} has no effect.
The same value is returned every time this function is called.
For a return value \tcode{p} and a memory resource \tcode{r},
\tcode{p->is_equal(r)} returns \tcode{\&r == p}.
\end{itemdescr}

\pnum
The \defn{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 \tcode{new_delete_resource()}.

\indexlibraryglobal{set_default_resource}%
\begin{itemdecl}
memory_resource* set_default_resource(memory_resource* r) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
If \tcode{r} is non-null,
sets the value of the default memory resource pointer to \tcode{r},
otherwise sets the default memory resource pointer to \tcode{new_delete_resource()}.

\pnum
\returns
The previous value of the default memory resource pointer.

\pnum
\remarks
Calling the \tcode{set_default_resource} and
\tcode{get_default_resource} functions shall not incur a data race\iref{intro.races}.
A call to the \tcode{set_default_resource} function
synchronizes with subsequent calls to
the \tcode{set_default_resource} and \tcode{get_default_resource} functions.
\end{itemdescr}

\indexlibraryglobal{get_default_resource}%
\begin{itemdecl}
memory_resource* get_default_resource() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The current value of the default memory resource pointer.
\end{itemdescr}

\rSec2[mem.res.pool]{Pool resource classes}

\rSec3[mem.res.pool.overview]{Classes \tcode{synchronized_pool_resource} and \tcode{unsynchronized_pool_resource}}

\pnum
The \tcode{synchronized_pool_resource} and
\tcode{unsynchronized_pool_resource} classes
(collectively called \defn{pool resource classes})
are general-purpose memory resources having the following qualities:
\begin{itemize}
\item
Each resource frees its allocated memory on destruction,
even if \tcode{deallocate} has not been called for some of the allocated blocks.
\item
A pool resource consists of a collection of \defn{pools},
serving requests for different block sizes.
Each individual pool manages a collection of \defn{chunks}
that are in turn divided into blocks of uniform size,
returned via calls to \tcode{do_allocate}.
Each call to \tcode{do_allocate(size, alignment)} is dispatched
to the pool serving the smallest blocks accommodating at least \tcode{size} bytes.
\item
When a particular pool is exhausted,
allocating a block from that pool results in the allocation
of an additional chunk of memory from the \defn{upstream allocator}
(supplied at construction), thus replenishing the pool.
With each successive replenishment,
the chunk size obtained increases geometrically.
\begin{note}
By allocating memory in chunks,
the pooling strategy increases the chance that consecutive allocations
will be close together in memory.
\end{note}
\item
Allocation requests that exceed the largest block size of any pool
are fulfilled directly from the upstream allocator.
\item
A \tcode{pool_options} struct may be passed to the pool resource constructors
to tune the largest block size and the maximum chunk size.
\end{itemize}

\pnum
A \tcode{synchronized_pool_resource} may be accessed from multiple threads
without external synchronization
and may have thread-specific pools to reduce synchronization costs.
An \tcode{unsynchronized_pool_resource} class may not be accessed
from multiple threads simultaneously
and thus avoids the cost of synchronization entirely
in single-threaded applications.

\indexlibraryglobal{pool_options}%
\indexlibraryglobal{synchronized_pool_resource}%
\indexlibraryglobal{unsynchronized_pool_resource}%
\begin{codeblock}
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;
  };
}
\end{codeblock}

\rSec3[mem.res.pool.options]{\tcode{pool_options} data members}

\pnum
The members of \tcode{pool_options}
comprise a set of constructor options for pool resources.
The effect of each option on the pool resource behavior is described below:

\indexlibrarymember{pool_options}{max_blocks_per_chunk}%
\begin{itemdecl}
size_t max_blocks_per_chunk;
\end{itemdecl}

\begin{itemdescr}
\pnum
The maximum number of blocks that will be allocated at once
from the upstream memory resource\iref{mem.res.monotonic.buffer}
to replenish a pool.
If the value of \tcode{max_blocks_per_chunk} is zero or
is greater than an \impldef{largest supported value to configure the maximum number of blocks to replenish a pool}
limit, that limit is used instead.
The implementation
may choose to use a smaller value than is specified in this member and
may use different values for different pools.
\end{itemdescr}

\indexlibrarymember{pool_options}{largest_required_pool_block}%
\begin{itemdecl}
size_t largest_required_pool_block;
\end{itemdecl}

\begin{itemdescr}
\pnum
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 \tcode{largest_required_pool_block} is zero or
is greater than an \impldef{largest supported value to configure the largest allocation satisfied directly by a pool}
limit, that limit is used instead.
The implementation may choose a pass-through threshold
larger than specified in this member.
\end{itemdescr}

\rSec3[mem.res.pool.ctor]{Constructors and destructors}

\indexlibraryctor{synchronized_pool_resource}%
\indexlibraryctor{unsynchronized_pool_resource}%
\begin{itemdecl}
synchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{upstream} is the address of a valid memory resource.

\pnum
\effects
Constructs a pool resource object that will obtain memory from \tcode{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 \tcode{upstream},
but will not own the resource to which \tcode{upstream} points.
\begin{note}
The intention is that calls to \tcode{upstream->allocate()}
will be substantially fewer than calls to \tcode{this->allocate()}
in most cases.
\end{note}
The behavior of the pooling mechanism is tuned
according to the value of the \tcode{opts} argument.

\pnum
\throws
Nothing unless \tcode{upstream->allocate()} throws.
It is unspecified if, or under what conditions,
this constructor calls \tcode{upstream->allocate()}.
\end{itemdescr}

\indexlibrarydtor{synchronized_pool_resource}%
\indexlibrarydtor{unsynchronized_pool_resource}%
\begin{itemdecl}
virtual ~synchronized_pool_resource();
virtual ~unsynchronized_pool_resource();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Calls \tcode{release()}.
\end{itemdescr}

\rSec3[mem.res.pool.mem]{Members}

\indexlibrarymember{release}{synchronized_pool_resource}%
\indexlibrarymember{release}{unsynchronized_pool_resource}%
\begin{itemdecl}
void release();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Calls \tcode{upstream_resource()->deallocate()} as necessary
to release all allocated memory.
\begin{note}
The memory is released back to \tcode{upstream_resource()}
even if \tcode{deallocate} has not been called
for some of the allocated blocks.
\end{note}
\end{itemdescr}

\indexlibrarymember{upstream_resource}{synchronized_pool_resource}%
\indexlibrarymember{upstream_resource}{unsynchronized_pool_resource}%
\begin{itemdecl}
memory_resource* upstream_resource() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{upstream} argument
provided to the constructor of this object.
\end{itemdescr}

\indexlibrarymember{options}{synchronized_pool_resource}%
\indexlibrarymember{options}{unsynchronized_pool_resource}%
\begin{itemdecl}
pool_options options() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\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 \impldef{default configuration of a pool}
defaults, and sizes may be rounded to unspecified granularity.
\end{itemdescr}

\indexlibrarymember{do_allocate}{synchronized_pool_resource}%
\indexlibrarymember{do_allocate}{unsynchronized_pool_resource}%
\begin{itemdecl}
void* do_allocate(size_t bytes, size_t alignment) override;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
If the pool selected for a block of size \tcode{bytes}
is unable to satisfy the memory request from its own internal data structures,
it will call \tcode{upstream_resource()->allocate()} to obtain more memory.
If \tcode{bytes} is larger than that which the largest pool can handle,
then memory will be allocated using \tcode{upstream_resource()->allocate()}.

\pnum
\returns
A pointer to allocated storage\iref{basic.stc.dynamic.allocation}
with a size of at least \tcode{bytes}.
The size and alignment of the allocated memory shall meet the requirements
for a class derived from \tcode{memory_resource}\iref{mem.res.class}.

\pnum
\throws
Nothing unless \tcode{upstream_resource()->allocate()} throws.
\end{itemdescr}

\indexlibrarymember{do_deallocate}{synchronized_pool_resource}%
\indexlibrarymember{do_deallocate}{unsynchronized_pool_resource}%
\begin{itemdecl}
void do_deallocate(void* p, size_t bytes, size_t alignment) override;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Returns the memory at \tcode{p} to the pool.
It is unspecified if, or under what circumstances,
this operation will result in a call to \tcode{upstream_resource()->deallocate()}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{do_is_equal}{synchronized_pool_resource}%
\indexlibrarymember{do_is_equal}{unsynchronized_pool_resource}%
\begin{itemdecl}
bool do_is_equal(const memory_resource& other) const noexcept override;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{this == \&other}.
\end{itemdescr}

\rSec2[mem.res.monotonic.buffer]{Class \tcode{monotonic_buffer_resource}}

\rSec3[mem.res.monotonic.buffer.general]{General}

\pnum
A \tcode{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.

\indexlibraryglobal{monotonic_buffer_resource}%
\begin{codeblock}
namespace std::pmr {
  class monotonic_buffer_resource : public memory_resource {
    memory_resource* upstream_rsrc;     // \expos
    void* current_buffer;               // \expos
    size_t next_buffer_size;            // \expos

  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_resource&) = delete;

    void release();
    memory_resource* upstream_resource() 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;
  };
}
\end{codeblock}

\rSec3[mem.res.monotonic.buffer.ctor]{Constructors and destructor}

\indexlibraryctor{monotonic_buffer_resource}%
\begin{itemdecl}
explicit monotonic_buffer_resource(memory_resource* upstream);
monotonic_buffer_resource(size_t initial_size, memory_resource* upstream);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{upstream} is the address of a valid memory resource.
\tcode{initial_size}, if specified, is greater than zero.

\pnum
\effects
Sets \tcode{upstream_rsrc} to \tcode{upstream} and
\tcode{current_buffer} to \keyword{nullptr}.
If \tcode{initial_size} is specified,
sets \tcode{next_buffer_size} to at least \tcode{initial_size};
otherwise sets \tcode{next_buffer_size} to an
\impldef{default \tcode{next_buffer_size} for a \tcode{monotonic_buffer_resource}} size.
\end{itemdescr}

\indexlibraryctor{monotonic_buffer_resource}%
\begin{itemdecl}
monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{upstream} is the address of a valid memory resource.
\tcode{buffer_size} is no larger than the number of bytes in \tcode{buffer}.

\pnum
\effects
Sets \tcode{upstream_rsrc} to \tcode{upstream},
\tcode{current_buffer} to \tcode{buffer}, and
\tcode{next_buffer_size} to \tcode{buffer_size} (but not less than 1),
then increases \tcode{next_buffer_size}
by an \impldef{growth factor for \tcode{monotonic_buffer_resource}} growth factor (which need not be integral).
\end{itemdescr}

\indexlibrarydtor{monotonic_buffer_resource}%
\begin{itemdecl}
~monotonic_buffer_resource();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Calls \tcode{release()}.
\end{itemdescr}


\rSec3[mem.res.monotonic.buffer.mem]{Members}

\indexlibrarymember{release}{monotonic_buffer_resource}%
\begin{itemdecl}
void release();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Calls \tcode{upstream_rsrc->deallocate()} as necessary
to release all allocated memory.
Resets \tcode{current_buffer} and \tcode{next_buffer_size}
to their initial values at construction.

\pnum
\begin{note}
The memory is released back to \tcode{upstream_rsrc}
even if some blocks that were allocated from \tcode{*this}
have not been deallocated from \tcode{*this}.
\end{note}
\end{itemdescr}

\indexlibrarymember{upstream_resource}{monotonic_buffer_resource}%
\begin{itemdecl}
memory_resource* upstream_resource() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of \tcode{upstream_rsrc}.
\end{itemdescr}

\indexlibrarymember{do_allocate}{monotonic_buffer_resource}%
\begin{itemdecl}
void* do_allocate(size_t bytes, size_t alignment) override;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
If the unused space in \tcode{current_buffer}
can fit a block with the specified \tcode{bytes} and \tcode{alignment},
then allocate the return block from \tcode{current_buffer};
otherwise set \tcode{current_buffer} to \tcode{upstream_rsrc->allocate(n, m)},
where \tcode{n} is not less than \tcode{max(bytes, next_buffer_size)} and
\tcode{m} is not less than \tcode{alignment},
and increase \tcode{next_buffer_size}
by an \impldef{growth factor for \tcode{monotonic_buffer_resource}} growth factor (which need not be integral),
then allocate the return block from the newly-allocated \tcode{current_buffer}.

\pnum
\returns
A pointer to allocated storage\iref{basic.stc.dynamic.allocation}
with a size of at least \tcode{bytes}.
The size and alignment of the allocated memory shall meet the requirements
for a class derived from \tcode{memory_resource}\iref{mem.res.class}.

\pnum
\throws
Nothing unless \tcode{upstream_rsrc->allocate()} throws.
\end{itemdescr}

\indexlibrarymember{do_deallocate}{monotonic_buffer_resource}%
\begin{itemdecl}
void do_deallocate(void* p, size_t bytes, size_t alignment) override;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
None.

\pnum
\throws
Nothing.

\pnum
\remarks
Memory used by this resource increases monotonically until its destruction.
\end{itemdescr}

\indexlibrarymember{do_is_equal}{monotonic_buffer_resource}%
\begin{itemdecl}
bool do_is_equal(const memory_resource& other) const noexcept override;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{this == \&other}.
\end{itemdescr}


\rSec1[allocator.adaptor]{Class template \tcode{scoped_allocator_adaptor}}

\rSec2[allocator.adaptor.syn]{Header \tcode{<scoped_allocator>} synopsis}

\indexheader{scoped_allocator}%
\begin{codeblock}
namespace std {
  // class template \tcode{scoped_allocator_adaptor}
  template<class OuterAlloc, class... InnerAlloc>
    class scoped_allocator_adaptor;

  // \ref{scoped.adaptor.operators}, scoped allocator operators
  template<class OuterA1, class OuterA2, class... InnerAllocs>
    bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
                    const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
}
\end{codeblock}

\pnum
The class template \tcode{scoped_allocator_adaptor} is an allocator template that
specifies an allocator resource (the outer allocator) to be used by a container (as any
other allocator does) and also specifies an inner allocator resource to be passed to the
constructor of every element within the container. This adaptor is instantiated with one
outer and zero or more inner allocator types. If instantiated with only one allocator
type, the inner allocator becomes the \tcode{scoped_allocator_adaptor} itself, thus
using the same allocator resource for the container and every element within the
container and, if the elements themselves are containers, each of their elements
recursively. If instantiated with more than one allocator, the first allocator is the
outer allocator for use by the container, the second allocator is passed to the
constructors of the container's elements, and, if the elements themselves are
containers, the third allocator is passed to the elements' elements, and so on. If
containers are nested to a depth greater than the number of allocators, the last
allocator is used repeatedly, as in the single-allocator case, for any remaining
recursions.
\begin{note}
The \tcode{scoped_allocator_adaptor} is derived from the outer
allocator type so it can be substituted for the outer allocator type in most
expressions.
\end{note}

\indexlibraryglobal{scoped_allocator_adaptor}%
\indexlibrarymember{outer_allocator_type}{scoped_allocator_adaptor}%
\indexlibrarymember{value_type}{scoped_allocator_adaptor}%
\indexlibrarymember{size_type}{scoped_allocator_adaptor}%
\indexlibrarymember{difference_type}{scoped_allocator_adaptor}%
\indexlibrarymember{pointer}{scoped_allocator_adaptor}%
\indexlibrarymember{const_pointer}{scoped_allocator_adaptor}%
\indexlibrarymember{void_pointer}{scoped_allocator_adaptor}%
\indexlibrarymember{const_void_pointer}{scoped_allocator_adaptor}%
\begin{codeblock}
namespace std {
  template<class OuterAlloc, class... InnerAllocs>
  class scoped_allocator_adaptor : public OuterAlloc {
  private:
    using OuterTraits = allocator_traits<OuterAlloc>;   // \expos
    scoped_allocator_adaptor<InnerAllocs...> inner;     // \expos

  public:
    using outer_allocator_type = OuterAlloc;
    using inner_allocator_type = @\seebelow@;

    using value_type           = OuterTraits::value_type;
    using size_type            = OuterTraits::size_type;
    using difference_type      = OuterTraits::difference_type;
    using pointer              = OuterTraits::pointer;
    using const_pointer        = OuterTraits::const_pointer;
    using void_pointer         = OuterTraits::void_pointer;
    using const_void_pointer   = OuterTraits::const_void_pointer;

    using propagate_on_container_copy_assignment = @\seebelow@;
    using propagate_on_container_move_assignment = @\seebelow@;
    using propagate_on_container_swap            = @\seebelow@;
    using is_always_equal                        = @\seebelow@;

    template<class Tp> struct rebind {
      using other = scoped_allocator_adaptor<
        OuterTraits::template rebind_alloc<Tp>, InnerAllocs...>;
    };

    scoped_allocator_adaptor();
    template<class OuterA2>
      scoped_allocator_adaptor(OuterA2&& outerAlloc,
                               const InnerAllocs&... innerAllocs) noexcept;

    scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
    scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;

    template<class OuterA2>
      scoped_allocator_adaptor(
        const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;
    template<class OuterA2>
      scoped_allocator_adaptor(
        scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;

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

    ~scoped_allocator_adaptor();

    inner_allocator_type& inner_allocator() noexcept;
    const inner_allocator_type& inner_allocator() const noexcept;
    outer_allocator_type& outer_allocator() noexcept;
    const outer_allocator_type& outer_allocator() const noexcept;

    pointer allocate(size_type n);
    pointer allocate(size_type n, const_void_pointer hint);
    void deallocate(pointer p, size_type n);
    size_type max_size() const;

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

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

    scoped_allocator_adaptor select_on_container_copy_construction() const;
  };

  template<class OuterAlloc, class... InnerAllocs>
    scoped_allocator_adaptor(OuterAlloc, InnerAllocs...)
      -> scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>;
}
\end{codeblock}

\rSec2[allocator.adaptor.types]{Member types}

\indexlibrarymember{inner_allocator_type}{scoped_allocator_adaptor}%
\begin{itemdecl}
using inner_allocator_type = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{scoped_allocator_adaptor<OuterAlloc>} if \tcode{sizeof...(InnerAllocs)} is
zero; otherwise,\\ \tcode{scoped_allocator_adaptor<InnerAllocs...>}.
\end{itemdescr}

\indexlibrarymember{propagate_on_container_copy_assignment}{scoped_allocator_adaptor}%
\begin{itemdecl}
using propagate_on_container_copy_assignment = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{true_type} if
\tcode{allocator_traits<A>::propagate_on_container_copy_assignment::value} is
\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and
\tcode{InnerAllocs...}; otherwise, \tcode{false_type}.
\end{itemdescr}

\indexlibrarymember{propagate_on_container_move_assignment}{scoped_allocator_adaptor}%
\begin{itemdecl}
using propagate_on_container_move_assignment = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{true_type} if
\tcode{allocator_traits<A>::propagate_on_container_move_assignment::value} is
\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and
\tcode{InnerAllocs...}; otherwise, \tcode{false_type}.
\end{itemdescr}

\indexlibrarymember{propagate_on_container_swap}{scoped_allocator_adaptor}%
\begin{itemdecl}
using propagate_on_container_swap = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{true_type} if
\tcode{allocator_traits<A>::propagate_on_container_swap::value} is
\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and
\tcode{InnerAllocs...}; otherwise, \tcode{false_type}.
\end{itemdescr}

\indexlibrarymember{is_always_equal}{scoped_allocator_adaptor}%
\begin{itemdecl}
using is_always_equal = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ctype \tcode{true_type} if
\tcode{allocator_traits<A>::is_always_equal::value} is
\tcode{true} for every \tcode{A} in the set of \tcode{OuterAlloc} and
\tcode{InnerAllocs...}; otherwise, \tcode{false_type}.
\end{itemdescr}

\rSec2[allocator.adaptor.cnstr]{Constructors}

\indexlibraryctor{scoped_allocator_adaptor}%
\begin{itemdecl}
scoped_allocator_adaptor();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Value-initializes the \tcode{OuterAlloc} base class and the \tcode{inner} allocator
object.
\end{itemdescr}

\indexlibraryctor{scoped_allocator_adaptor}%
\begin{itemdecl}
template<class OuterA2>
  scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<OuterAlloc, OuterA2>} is \tcode{true}.

\pnum
\effects
Initializes the \tcode{OuterAlloc} base class with
\tcode{std::forward<OuterA2>(outerAlloc)} and \tcode{inner} with \tcode{innerAllocs...}
(hence recursively initializing each allocator within the adaptor with the corresponding
allocator from the argument list).
\end{itemdescr}

\indexlibraryctor{scoped_allocator_adaptor}%
\begin{itemdecl}
scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes each allocator within the adaptor with the corresponding allocator
from \tcode{other}.
\end{itemdescr}

\indexlibraryctor{scoped_allocator_adaptor}%
\begin{itemdecl}
scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Move constructs each allocator within the adaptor with the corresponding allocator
from \tcode{other}.
\end{itemdescr}

\indexlibraryctor{scoped_allocator_adaptor}%
\begin{itemdecl}
template<class OuterA2>
  scoped_allocator_adaptor(
    const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<OuterAlloc, const OuterA2\&>} is \tcode{true}.

\pnum
\effects
Initializes each allocator within the adaptor with the corresponding allocator
from \tcode{other}.
\end{itemdescr}

\indexlibraryctor{scoped_allocator_adaptor}%
\begin{itemdecl}
template<class OuterA2>
  scoped_allocator_adaptor(scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<OuterAlloc, OuterA2>} is \tcode{true}.

\pnum
\effects
Initializes each allocator within the adaptor with the corresponding allocator rvalue
from \tcode{other}.
\end{itemdescr}

\rSec2[allocator.adaptor.members]{Members}

\pnum
In the \tcode{construct} member functions,
\tcode{\placeholdernc{OUTERMOST}(x)} is
\tcode{\placeholdernc{OUTERMOST}(x.outer_allocator())} if
the expression \tcode{x.outer_allocator()} is
valid~\iref{temp.deduct} and
\tcode{x} otherwise;
\tcode{\placeholdernc{OUTERMOST_ALLOC_TRAITS}(x)} is
\tcode{allocator_traits<remove_reference_t<decltype(\placeholdernc{OUTERMOST}(x))>>}.
\begin{note}
\tcode{\placeholdernc{OUTERMOST}(x)} and
\tcode{\placeholdernc{OUTERMOST_ALL\-OC_TRAITS}(x)} are recursive operations. It
is incumbent upon the definition of \tcode{outer_allocator()} to ensure that the
recursion terminates. It will terminate for all instantiations of
\tcode{scoped_allocator_adaptor}.
\end{note}

\indexlibrarymember{inner_allocator}{scoped_allocator_adaptor}%
\begin{itemdecl}
inner_allocator_type& inner_allocator() noexcept;
const inner_allocator_type& inner_allocator() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{*this} if \tcode{sizeof...(InnerAllocs)} is zero; otherwise,
\tcode{inner}.
\end{itemdescr}

\indexlibrarymember{outer_allocator}{scoped_allocator_adaptor}%
\begin{itemdecl}
outer_allocator_type& outer_allocator() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{static_cast<OuterAlloc\&>(*this)}.
\end{itemdescr}

\indexlibrarymember{outer_allocator}{scoped_allocator_adaptor}%
\begin{itemdecl}
const outer_allocator_type& outer_allocator() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{static_cast<const OuterAlloc\&>(*this)}.
\end{itemdescr}

\indexlibrarymember{allocate}{scoped_allocator_adaptor}%
\begin{itemdecl}
pointer allocate(size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)}.
\end{itemdescr}

\indexlibrarymember{allocate}{scoped_allocator_adaptor}%
\begin{itemdecl}
pointer allocate(size_type n, const_void_pointer hint);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)}.
\end{itemdescr}

\indexlibrarymember{deallocate}{scoped_allocator_adaptor}%
\begin{itemdecl}
void deallocate(pointer p, size_type n) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
As if by:
\tcode{allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n);}
\end{itemdescr}

\indexlibrarymember{max_size}{scoped_allocator_adaptor}%
\begin{itemdecl}
size_type max_size() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{allocator_traits<OuterAlloc>::max_size(outer_allocator())}.
\end{itemdescr}

\indexlibrarymember{construct}{scoped_allocator_adaptor}%
\begin{itemdecl}
template<class T, class... Args>
  void construct(T* p, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
apply([p, this](auto&&... newargs) {
        @\placeholdernc{OUTERMOST_ALLOC_TRAITS}@(*this)::construct(
          @\placeholdernc{OUTERMOST}@(*this), p,
          std::forward<decltype(newargs)>(newargs)...);
      },
      uses_allocator_construction_args<T>(inner_allocator(),
                                          std::forward<Args>(args)...));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{destroy}{scoped_allocator_adaptor}%
\begin{itemdecl}
template<class T>
  void destroy(T* p);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Calls \tcode{\placeholdernc{OUTERMOST_ALLOC_TRAITS}(*this)::destroy(\placeholdernc{OUTERMOST}(*this), p)}.
\end{itemdescr}

\indexlibrarymember{select_on_container_copy_construction}{scoped_allocator_adaptor}%
\begin{itemdecl}
scoped_allocator_adaptor select_on_container_copy_construction() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A new \tcode{scoped_allocator_adaptor} object
where each allocator \tcode{a1} within the adaptor
is initialized with
\tcode{allocator_traits<A1>::select_on_container_copy_construction(a2)},
where \tcode{A1} is the type of \tcode{a1} and
\tcode{a2} is the corresponding allocator in \tcode{*this}.
\end{itemdescr}

\rSec2[scoped.adaptor.operators]{Operators}

\indexlibrarymember{operator==}{scoped_allocator_adaptor}%
\begin{itemdecl}
template<class OuterA1, class OuterA2, class... InnerAllocs>
  bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
                  const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
If \tcode{sizeof...(InnerAllocs)} is zero,
\begin{codeblock}
a.outer_allocator() == b.outer_allocator()
\end{codeblock}
otherwise
\begin{codeblock}
a.outer_allocator() == b.outer_allocator() && a.inner_allocator() == b.inner_allocator()
\end{codeblock}
\end{itemdescr}
