Standard library header <memory>

From cppreference.net
< cpp‎ | header
 
 
Standard library headers
 

This header is part of the dynamic memory management library.

Includes

(C++20)
Three-way comparison operator support

Classes

Pointer traits
provides information about pointer-like types
(class template)
Garbage collector support
(C++11)(removed in C++23)
lists pointer safety models
(enum)
Allocators
the default allocator
(class template)
provides information about allocator types
(class template)
records the address and the actual size of storage allocated by allocate_at_least
(class template)
checks if the specified type supports uses-allocator construction
(class template)
Uninitialized storage
(deprecated in C++17)(removed in C++20)
an iterator that allows standard algorithms to store results in uninitialized memory
(class template)
Smart pointers
smart pointer with unique object ownership semantics
(class template)
smart pointer with shared object ownership semantics
(class template)
(C++11)
weak reference to an object managed by std::shared_ptr
(class template)
(deprecated in C++11)(removed in C++17)
smart pointer with strict object ownership semantics
(class template)
Smart pointer adaptors
(C++23)
interoperates with foreign pointer setters and resets a smart pointer on destruction
(class template)
interoperates with foreign pointer setters, obtains the initial pointer value from a smart pointer, and resets it on destruction
(class template)
Types for composite class design
(C++26)
a wrapper containing dynamically-allocated object with value-like semantics
(class template)
a polymorphic wrapper containing dynamically-allocated object with value-like semantics
(class template)
Helper classes
atomic shared pointer
(class template specialization)
atomic weak pointer
(class template specialization)
provides mixed-type owner-based ordering of shared and weak pointers
(class template)
provides owner-based hashing for shared and weak pointers
(class)
provides mixed-type owner-based equal comparisons of shared and weak pointers
(class)
allows an object to create a shared_ptr referring to itself
(class template)
exception thrown when accessing a weak_ptr which refers to already destroyed object
(class)
default deleter for unique_ptr
(class template)
hash support for std::unique_ptr
(class template specialization)
hash support for std::shared_ptr
(class template specialization)
hash support for std::indirect
(class template specialization)
Forward declarations
Defined in header <functional>
(C++11)
hash function object
(class template)
Defined in header <atomic>
(C++11)
atomic class template and specializations for bool, integral, floating-point,(since C++20) and pointer types
(class template)

Tags

a tag used to select allocator-aware constructors
(tag)

Functions

Uses-allocator construction
prepares the argument list matching the flavor of uses-allocator construction required by the given type
(function template)
creates an object of the given type by means of uses-allocator construction
(function template)
creates an object of the given type at specified memory location by means of uses-allocator construction
(function template)
Miscellaneous
obtains a raw pointer from a pointer-like type
(function template)
(C++11)
obtains actual address of an object, even if the & operator is overloaded
(function template)
(C++11)
aligns a pointer in a buffer
(function)
informs the compiler that a pointer is aligned
(function template)
checks whether the pointer points to an object whose alignment has at least the given value
(function template)
Explicit lifetime management
implicitly creates objects in given storage with the object representation reused
(function template)
Garbage collector support
(C++11)(removed in C++23)
declares that an object can not be recycled
(function)
(C++11)(removed in C++23)
declares that an object can be recycled
(function template)
(C++11)(removed in C++23)
declares that a memory area does not contain traceable pointers
(function)
(C++11)(removed in C++23)
cancels the effect of std::declare_no_pointers
(function)
(C++11)(removed in C++23)
returns the current pointer safety model
(function)
Uninitialized storage
copies a range of objects to an uninitialized area of memory
(function template)
copies a number of objects to an uninitialized area of memory
(function template)
copies an object to an uninitialized area of memory, defined by a range
(function template)
copies an object to an uninitialized area of memory, defined by a start and a count
(function template)
moves a range of objects to an uninitialized area of memory
(function template)
moves a number of objects to an uninitialized area of memory
(function template)
constructs objects by default-initialization in an uninitialized area of memory, defined by a range
(function template)
constructs objects by default-initialization in an uninitialized area of memory, defined by a start and a count
(function template)
constructs objects by value-initialization in an uninitialized area of memory, defined by a range
(function template)
constructs objects by value-initialization in an uninitialized area of memory, defined by a start and a count
(function template)
creates an object at a given address
(function template)
destroys an object at a given address
(function template)
(C++17)
destroys a range of objects
(function template)
(C++17)
destroys a number of objects in a range
(function template)
(deprecated in C++17)(removed in C++20)
obtains uninitialized storage
(function template)
(deprecated in C++17)(removed in C++20)
frees uninitialized storage
(function template)
Smart pointer non-member operations
creates a unique pointer that manages a new object
(function template)
compares to another unique_ptr or with nullptr
(function template)
creates a shared pointer that manages a new object
(function template)
creates a shared pointer that manages a new object allocated using an allocator
(function template)
applies static_cast, dynamic_cast, const_cast, or reinterpret_cast to the stored pointer
(function template)
returns the deleter of specified type, if owned
(function template)
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)
compares with another shared_ptr or with nullptr
(function template)
outputs the value of the stored pointer to an output stream
(function template)
outputs the value of the managed pointer to an output stream
(function template)
specializes the std::swap algorithm
(function template)
specializes the std::swap algorithm
(function template)
specializes the std::swap algorithm
(function template)
Smart pointer adaptor creation
(C++23)
creates an out_ptr_t with an associated smart pointer and resetting arguments
(function template)
(C++23)
creates an inout_ptr_t with an associated smart pointer and resetting arguments
(function template)
specializes atomic operations for std::shared_ptr
(function template)

Function-like entities

Defined in namespace std::ranges
Uninitialized storage
copies a range of objects to an uninitialized area of memory
(algorithm function object)
copies a number of objects to an uninitialized area of memory
(algorithm function object)
copies an object to an uninitialized area of memory, defined by a range
(algorithm function object)
copies an object to an uninitialized area of memory, defined by a start and a count
(algorithm function object)
moves a range of objects to an uninitialized area of memory
(algorithm function object)
moves a number of objects to an uninitialized area of memory
(algorithm function object)
constructs objects by default-initialization in an uninitialized area of memory, defined by a range
(algorithm function object)
constructs objects by default-initialization in an uninitialized area of memory, defined by a start and count
(algorithm function object)
constructs objects by value-initialization in an uninitialized area of memory, defined by a range
(algorithm function object)
constructs objects by value-initialization in an uninitialized area of memory, defined by a start and a count
(algorithm function object)
creates an object at a given address
(algorithm function object)
destroys an object at a given address
(algorithm function object)
destroys a range of objects
(algorithm function object)
destroys a number of objects in a range
(algorithm function object)

Synopsis

#include <compare>
 
namespace std {
  // pointer Traits
  template<class Ptr>
  struct pointer_traits; // freestanding
  template<class T>
  struct pointer_traits<T*>; // freestanding
 
  // 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
 
  // 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);
 
  // explicit lifetime management
  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;
  template<class T>
  T* trivially_relocate(T* first, T* last, T* result); // freestanding
  template<class T>
  constexpr T* relocate(T* first, T* last, T* result); // freestanding
 
  // allocator argument tag
  struct allocator_arg_t
  {
    explicit allocator_arg_t() = default;
  };                                                // freestanding
  inline constexpr allocator_arg_t allocator_arg{}; // freestanding
 
  // uses_allocator
  template<class T, class Alloc>
  struct uses_allocator; // freestanding
 
  // uses_allocator
  template<class T, class Alloc>
  constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value; // freestanding
 
  // 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, /*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);
 
  // allocator Traits
  template<class Alloc>
  struct allocator_traits; // freestanding
 
  template<class Pointer, class SizeType = size_t>
  struct allocation_result
  { // freestanding
    Pointer ptr;
    SizeType count;
  };
 
  // the default allocator
  template<class T>
  class allocator;
  template<class T, class U>
  constexpr bool operator==(const allocator<T>&, const allocator<U>&) noexcept;
 
  // addressof
  template<class T>
  constexpr T* addressof(T& r) noexcept; // freestanding
  template<class T>
  const T* addressof(const T&&) = delete; // freestanding
 
  // specialized algorithms
  // special memory concepts
  template<class I>
  concept no-throw-input-iterator = /* see description */; // exposition-only
  template<class I>
  concept no-throw-forward-iterator = /* see description */; // exposition-only
  template<class S, class I>
  concept no-throw-sentinel-for = /* see description */; // exposition-only
  template<class R>
  concept no-throw-input-range = /* see description */; // exposition-only
  template<class R>
  concept no-throw-forward-range = /* see description */; // exposition-only
 
  template<class NoThrowForwardIter>
  constexpr void uninitialized_default_construct(NoThrowForwardIter first, // freestanding
                                                 NoThrowForwardIter last);
  template<class ExecutionPolicy, class NoThrowForwardIter>
  void uninitialized_default_construct(ExecutionPolicy&& exec, // freestanding-deleted,
                                       NoThrowForwardIter first,
                                       NoThrowForwardIter last);
  template<class NoThrowForwardIter, class Size>
  constexpr NoThrowForwardIter uninitialized_default_construct_n(NoThrowForwardIter first,
                                                                 Size n); // freestanding
  template<class ExecutionPolicy, class NoThrowForwardIter, class Size>
  NoThrowForwardIter uninitialized_default_construct_n(
    ExecutionPolicy&& exec, // freestanding-deleted,
    NoThrowForwardIter first,
    Size n);
 
  namespace ranges {
    template<no-throw-forward-iterator I, no-throw-sentinel-for<I> S>
      requires default_initializable<iter_value_t<I>>
    constexpr I uninitialized_default_construct(I first, S last); // freestanding
    template<no-throw-forward-range R>
      requires default_initializable<range_value_t<R>>
    constexpr borrowed_iterator_t<R> uninitialized_default_construct(
      R&& r); // freestanding
 
    template<no-throw-forward-iterator I>
      requires default_initializable<iter_value_t<I>>
    constexpr I uninitialized_default_construct_n(I first, // freestanding
                                                  iter_difference_t<I> n);
  }
 
  template<class NoThrowForwardIter>
  constexpr void uninitialized_value_construct(NoThrowForwardIter first, // freestanding
                                               NoThrowForwardIter last);
  template<class ExecutionPolicy, class NoThrowForwardIter>
  void uninitialized_value_construct(ExecutionPolicy&& exec, // freestanding-deleted,
                                     NoThrowForwardIter first,
                                     NoThrowForwardIter last);
  template<class NoThrowForwardIter, class Size>
  constexpr NoThrowForwardIter uninitialized_value_construct_n(NoThrowForwardIter first,
                                                               Size n); // freestanding
  template<class ExecutionPolicy, class NoThrowForwardIter, class Size>
  NoThrowForwardIter uninitialized_value_construct_n(
    ExecutionPolicy&& exec, // freestanding-deleted,
    NoThrowForwardIter first,
    Size n);
 
  namespace ranges {
    template<no-throw-forward-iterator I, no-throw-sentinel-for<I> S>
      requires default_initializable<iter_value_t<I>>
    constexpr I uninitialized_value_construct(I first, S last); // freestanding
    template<no-throw-forward-range R>
      requires default_initializable<range_value_t<R>>
    constexpr borrowed_iterator_t<R> uninitialized_value_construct(R&& r); // freestanding
 
    template<no-throw-forward-iterator I>
      requires default_initializable<iter_value_t<I>>
    constexpr I uninitialized_value_construct_n(I first, // freestanding
                                                iter_difference_t<I> n);
  }
 
  template<class InputIter, class NoThrowForwardIter>
  constexpr NoThrowForwardIter uninitialized_copy(InputIter first, // freestanding
                                                  InputIter last,
                                                  NoThrowForwardIter result);
  template<class ExecutionPolicy, class ForwardIter, class NoThrowForwardIter>
  NoThrowForwardIter uninitialized_copy(ExecutionPolicy&& exec, // freestanding-deleted,
                                        ForwardIter first,
                                        ForwardIter last,
                                        NoThrowForwardIter result);
  template<class InputIter, class Size, class NoThrowForwardIter>
  constexpr NoThrowForwardIter uninitialized_copy_n(InputIter first, // freestanding
                                                    Size n,
                                                    NoThrowForwardIter result);
  template<class ExecutionPolicy,
           class ForwardIter,
           class Size,
           class NoThrowForwardIter>
  NoThrowForwardIter uninitialized_copy_n(ExecutionPolicy&& exec, // freestanding-deleted,
                                          ForwardIter first,
                                          Size n,
                                          NoThrowForwardIter result);
 
  namespace ranges {
    template<class I, class O>
    using uninitialized_copy_result = in_out_result<I, O>; // freestanding
    template<input_iterator I,
             sentinel_for<I> S1,
             no-throw-forward-iterator O,
             no-throw-sentinel-for<O> S2>
      requires 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<input_range IR, no-throw-forward-range OR>
      requires 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 uninitialized_copy_n_result = in_out_result<I, O>; // freestanding
    template<input_iterator I,
             no-throw-forward-iterator O,
             no-throw-sentinel-for<O> S>
      requires 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<class InputIter, class NoThrowForwardIter>
  constexpr NoThrowForwardIter uninitialized_move(InputIter first, // freestanding
                                                  InputIter last,
                                                  NoThrowForwardIter result);
  template<class ExecutionPolicy, class ForwardIter, class NoThrowForwardIter>
  NoThrowForwardIter uninitialized_move(ExecutionPolicy&& exec, // freestanding-deleted,
                                        ForwardIter first,
                                        ForwardIter last,
                                        NoThrowForwardIter result);
  template<class InputIter, class Size, class NoThrowForwardIter>
  constexpr pair<InputIter, NoThrowForwardIter> uninitialized_move_n(
    InputIter first,
    Size n, // freestanding
    NoThrowForwardIter result);
  template<class ExecutionPolicy, class ForwardIter, class Size, class NoThrowForwardIter>
  pair<ForwardIter, NoThrowForwardIter> uninitialized_move_n(
    ExecutionPolicy&& exec, // freestanding-deleted,
    ForwardIter first,
    Size n,
    NoThrowForwardIter result);
 
  namespace ranges {
    template<class I, class O>
    using uninitialized_move_result = in_out_result<I, O>; // freestanding
    template<input_iterator I,
             sentinel_for<I> S1,
             no-throw-forward-iterator O,
             no-throw-sentinel-for<O> S2>
      requires 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<input_range IR, no-throw-forward-range OR>
      requires 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 uninitialized_move_n_result = in_out_result<I, O>; // freestanding
    template<input_iterator I,
             no-throw-forward-iterator O,
             no-throw-sentinel-for<O> S>
      requires 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<class NoThrowForwardIter, class T>
  constexpr void uninitialized_fill(NoThrowForwardIter first, // freestanding
                                    NoThrowForwardIter last,
                                    const T& x);
  template<class ExecutionPolicy, class NoThrowForwardIter, class T>
  void uninitialized_fill(ExecutionPolicy&& exec, // freestanding-deleted,
                          NoThrowForwardIter first,
                          NoThrowForwardIter last,
                          const T& x);
  template<class NoThrowForwardIter, class Size, class T>
  constexpr NoThrowForwardIter uninitialized_fill_n(NoThrowForwardIter first,
                                                    Size n,
                                                    const T& x); // freestanding
  template<class ExecutionPolicy, class NoThrowForwardIter, class Size, class T>
  NoThrowForwardIter uninitialized_fill_n(ExecutionPolicy&& exec, // freestanding-deleted,
                                          NoThrowForwardIter first,
                                          Size n,
                                          const T& x);
 
  namespace ranges {
    template<no-throw-forward-iterator I, no-throw-sentinel-for<I> S, class T>
      requires constructible_from<iter_value_t<I>, const T&>
    constexpr I uninitialized_fill(I first, S last, const T& x); // freestanding
    template<no-throw-forward-range R, class T>
      requires constructible_from<range_value_t<R>, const T&>
    constexpr borrowed_iterator_t<R> uninitialized_fill(R&& r,
                                                        const T& x); // freestanding
 
    template<no-throw-forward-iterator I, class T>
      requires constructible_from<iter_value_t<I>, const T&>
    constexpr I uninitialized_fill_n(I first, // freestanding
                                     iter_difference_t<I> n,
                                     const T& x);
  }
 
  // 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
  }
 
  // destroy
  template<class T>
  constexpr void destroy_at(T* location); // freestanding
  template<class NoThrowForwardIter>
  constexpr void destroy(NoThrowForwardIter first, // freestanding
                         NoThrowForwardIter last);
  template<class ExecutionPolicy, class NoThrowForwardIter>
  void destroy(ExecutionPolicy&& exec, // freestanding-deleted,
               NoThrowForwardIter first,
               NoThrowForwardIter last);
  template<class NoThrowForwardIter, class Size>
  constexpr NoThrowForwardIter destroy_n(NoThrowForwardIter first, // freestanding
                                         Size n);
  template<class ExecutionPolicy, class NoThrowForwardIter, class Size>
  NoThrowForwardIter destroy_n(ExecutionPolicy&& exec, // freestanding-deleted,
                               NoThrowForwardIter first,
                               Size n);
 
  namespace ranges {
    template<destructible T>
    constexpr void destroy_at(T* location) noexcept; // freestanding
 
    template<no-throw-input-iterator I, no-throw-sentinel-for<I> S>
      requires destructible<iter_value_t<I>>
    constexpr I destroy(I first, S last) noexcept; // freestanding
    template<no-throw-input-range R>
      requires destructible<range_value_t<R>>
    constexpr borrowed_iterator_t<R> destroy(R&& r) noexcept; // freestanding
 
    template<no-throw-input-iterator I>
      requires destructible<iter_value_t<I>>
    constexpr I destroy_n(I first, iter_difference_t<I> n) noexcept; // freestanding
  }
 
  // class template 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); // T is not array
  template<class T>
  constexpr unique_ptr<T> make_unique(size_t n); // T is U[]
  template<class T, class... Args>
  /* unspecified */ make_unique(Args&&...) = delete; // T is U[N]
 
  template<class T>
  constexpr unique_ptr<T> make_unique_for_overwrite(); // T is not array
  template<class T>
  constexpr unique_ptr<T> make_unique_for_overwrite(size_t n); // T is U[]
  template<class T, class... Args>
  /* unspecified */ make_unique_for_overwrite(Args&&...) = delete; // T is U[N]
 
  template<class T, class D>
  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>
  bool operator<(const unique_ptr<T1, D1>& x,
                 const unique_ptr<T2, D2>& y); // freestanding
  template<class T1, class D1, class T2, class D2>
  bool operator>(const unique_ptr<T1, D1>& x,
                 const unique_ptr<T2, D2>& y); // freestanding
  template<class T1, class D1, class T2, class D2>
  bool operator<=(const unique_ptr<T1, D1>& x,
                  const unique_ptr<T2, D2>& y); // freestanding
  template<class T1, class D1, class T2, class D2>
  bool operator>=(const unique_ptr<T1, D1>& x,
                  const unique_ptr<T2, D2>& y); // freestanding
  template<class T1, class D1, class T2, class D2>
    requires three_way_comparable_with<typename unique_ptr<T1, D1>::pointer,
                                       typename unique_ptr<T2, D2>::pointer>
  compare_three_way_result_t<typename unique_ptr<T1, D1>::pointer,
                             typename unique_ptr<T2, D2>::pointer>
  operator<=>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); // 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 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);
 
  // class bad_weak_ptr
  class bad_weak_ptr;
 
  // class template shared_ptr
  template<class T>
  class shared_ptr;
 
  // shared_ptr creation
  template<class T, class... Args>
  shared_ptr<T> make_shared(Args&&... args); // T is not array
  template<class T, class A, class... Args>
  shared_ptr<T> allocate_shared(const A& a, Args&&... args); // T is not array
 
  template<class T>
  shared_ptr<T> make_shared(size_t N); // T is U[]
  template<class T, class A>
  shared_ptr<T> allocate_shared(const A& a, size_t N); // T is U[]
 
  template<class T>
  shared_ptr<T> make_shared(); // T is U[N]
  template<class T, class A>
  shared_ptr<T> allocate_shared(const A& a); // T is U[N]
 
  template<class T>
  shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // T is U[]
  template<class T, class A>
  shared_ptr<T> allocate_shared(const A& a,
                                size_t N,
                                const remove_extent_t<T>& u); // T is U[]
 
  template<class T>
  shared_ptr<T> make_shared(const remove_extent_t<T>& u); // T is U[N]
  template<class T, class A>
  shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& u); // T is U[N]
 
  template<class T>
  shared_ptr<T> make_shared_for_overwrite(); // T is not U[]
  template<class T, class A>
  shared_ptr<T> allocate_shared_for_overwrite(const A& a); // T is not U[]
 
  template<class T>
  shared_ptr<T> make_shared_for_overwrite(size_t N); // T is U[]
  template<class T, class A>
  shared_ptr<T> allocate_shared_for_overwrite(const A& a, size_t N); // T is U[]
 
  // shared_ptr comparisons
  template<class T, class U>
  bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
  strong_ordering operator<=>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
 
  template<class T>
  bool operator==(const shared_ptr<T>& x, nullptr_t) noexcept;
  template<class T>
  strong_ordering operator<=>(const shared_ptr<T>& x, nullptr_t) noexcept;
 
  // shared_ptr specialized algorithms
  template<class T>
  void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
 
  // shared_ptr casts
  template<class T, class U>
  shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
  shared_ptr<T> static_pointer_cast(shared_ptr<U>&& r) noexcept;
  template<class T, class U>
  shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
  shared_ptr<T> dynamic_pointer_cast(shared_ptr<U>&& r) noexcept;
  template<class T, class U>
  shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
  shared_ptr<T> const_pointer_cast(shared_ptr<U>&& r) noexcept;
  template<class T, class U>
  shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;
  template<class T, class U>
  shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U>&& r) noexcept;
 
  // shared_ptr get_deleter
  template<class D, class T>
  D* get_deleter(const shared_ptr<T>& p) noexcept;
 
  // 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);
 
  // class template weak_ptr
  template<class T>
  class weak_ptr;
 
  // weak_ptr specialized algorithms
  template<class T>
  void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
 
  // class template owner_less
  template<class T = void>
  struct owner_less;
 
  // struct owner_hash
  struct owner_hash;
 
  // struct owner_equal
  struct owner_equal;
 
  // class template enable_shared_from_this
  template<class T>
  class enable_shared_from_this;
 
  // 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>>;
 
  // 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>>;
 
  // class template out_ptr_t
  template<class Smart, class Pointer, class... Args>
  class out_ptr_t; // freestanding
 
  // function template out_ptr
  template<class Pointer = void, class Smart, class... Args>
  auto out_ptr(Smart& s, Args&&... args); // freestanding
 
  // class template inout_ptr_t
  template<class Smart, class Pointer, class... Args>
  class inout_ptr_t; // freestanding
 
  // function template inout_ptr
  template<class Pointer = void, class Smart, class... Args>
  auto inout_ptr(Smart& s, Args&&... args); // freestanding
 
  // class template indirect
  template<class T, class Allocator = allocator<T>>
  class indirect;
 
  // hash support
  template<class T, class Alloc>
  struct hash<indirect<T, Alloc>>;
 
  // class template 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>>;
  }
}

Helper concepts

Note: These names are only for exposition, they are not part of the interface.

template<class I>
concept no-throw-input-iterator = // exposition only
  input_iterator<I> &&
  is_lvalue_reference_v<iter_reference_t<I>> &&
  same_as<remove_cvref_t<iter_reference_t<I>>, iter_value_t<I>>;
 
template<class S, class I>
concept no-throw-sentinel-for = sentinel_for<S, I>; // exposition only
 
template<class R>
concept no-throw-input-range = // exposition only
  ranges::range<R> &&
  no-throw-input-iterator<ranges::iterator_t<R>> &&
  no-throw-sentinel-for<ranges::sentinel_t<R>, ranges::iterator_t<R>>;
 
template<class I>
concept no-throw-forward-iterator = // exposition only
  no-throw-input-iterator<I> &&
  forward_iterator<I> &&
  no-throw-sentinel-for<I, I>;
 
template<class R>
concept no-throw-forward-range = // exposition only
  no-throw-input-range<R> &&
  no-throw-forward-iterator<ranges::iterator_t<R>>;

Class template std::pointer_traits

namespace std {
  template<class Ptr>
  struct pointer_traits
  {
    /* see description */;
  };
 
  template<class T>
  struct pointer_traits<T*>
  {
    using pointer         = T*;
    using element_type    = T;
    using difference_type = ptrdiff_t;
 
    template<class U>
    using rebind = U*;
 
    static constexpr pointer pointer_to(/* see description */ r) noexcept;
  };
}

Class std::allocator_arg_t

namespace std {
  struct allocator_arg_t { explicit allocator_arg_t() = default; };
  inline constexpr allocator_arg_t allocator_arg{};
}

Class template std::allocator_traits

namespace std {
  template<class Alloc>
  struct allocator_traits
  {
    using allocator_type                         = Alloc;
 
    using value_type                             = typename Alloc::value_type;
 
    using pointer                                = /* see description */;
    using const_pointer                          = /* see description */;
    using void_pointer                           = /* see description */;
    using const_void_pointer                     = /* see description */;
 
    using difference_type                        = /* see description */;
    using size_type                              = /* see description */;
 
    using propagate_on_container_copy_assignment = /* see description */;
    using propagate_on_container_move_assignment = /* see description */;
    using propagate_on_container_swap            = /* see description */;
    using is_always_equal                        = /* see description */;
 
    template<class T>
    using rebind_alloc = /* see description */;
    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);
  };
}

Class template std::allocator

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

Class template std::default_delete

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

Class template std::unique_ptr

namespace std {
  template<class T, class D = default_delete<T>>
  class unique_ptr
  {
  public:
    using pointer      = /* see description */;
    using element_type = T;
    using deleter_type = D;
 
    // constructors
    constexpr unique_ptr() noexcept;
    constexpr explicit unique_ptr(type_identity_t<pointer> p) noexcept;
    constexpr unique_ptr(type_identity_t<pointer> p, /* see description */ d1) noexcept;
    constexpr unique_ptr(type_identity_t<pointer> p, /* see description */ 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;
 
    // 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;
 
    // observers
    constexpr add_lvalue_reference_t<T> operator*() const noexcept(/* see description */);
    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;
 
    // 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;
  };
 
  template<class T, class D>
  class unique_ptr<T[], D>
  {
  public:
    using pointer      = /* see description */;
    using element_type = T;
    using deleter_type = D;
 
    // constructors
    constexpr unique_ptr() noexcept;
    template<class U>
    constexpr explicit unique_ptr(U p) noexcept;
    template<class U>
    constexpr unique_ptr(U p, /* see description */ d) noexcept;
    template<class U>
    constexpr unique_ptr(U p, /* see description */ 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;
 
    // 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;
 
    // 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;
  };
}

Class std::bad_weak_ptr

namespace std {
  class bad_weak_ptr : public exception
  {
  public:
    // for the specification of the special member functions
    const char* what() const noexcept override;
  };
}

Class template std::shared_ptr

namespace std {
  template<class T>
  class shared_ptr
  {
  public:
    using element_type = remove_extent_t<T>;
    using weak_type    = weak_ptr<T>;
 
    // constructors
    constexpr shared_ptr() noexcept;
    constexpr shared_ptr(nullptr_t) noexcept
      : shared_ptr()
    {
    }
    template<class Y>
    explicit shared_ptr(Y* p);
    template<class Y, class D>
    shared_ptr(Y* p, D d);
    template<class Y, class D, class A>
    shared_ptr(Y* p, D d, A a);
    template<class D>
    shared_ptr(nullptr_t p, D d);
    template<class D, class A>
    shared_ptr(nullptr_t p, D d, A a);
    template<class Y>
    shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;
    template<class Y>
    shared_ptr(shared_ptr<Y>&& r, element_type* p) noexcept;
    shared_ptr(const shared_ptr& r) noexcept;
    template<class Y>
    shared_ptr(const shared_ptr<Y>& r) noexcept;
    shared_ptr(shared_ptr&& r) noexcept;
    template<class Y>
    shared_ptr(shared_ptr<Y>&& r) noexcept;
    template<class Y>
    explicit shared_ptr(const weak_ptr<Y>& r);
    template<class Y, class D>
    shared_ptr(unique_ptr<Y, D>&& r);
 
    // destructor
    ~shared_ptr();
 
    // assignment
    shared_ptr& operator=(const shared_ptr& r) noexcept;
    template<class Y>
    shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    shared_ptr& operator=(shared_ptr&& r) noexcept;
    template<class Y>
    shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
    template<class Y, class D>
    shared_ptr& operator=(unique_ptr<Y, D>&& r);
 
    // modifiers
    void swap(shared_ptr& r) noexcept;
    void reset() noexcept;
    template<class Y>
    void reset(Y* p);
    template<class Y, class D>
    void reset(Y* p, D d);
    template<class Y, class D, class A>
    void reset(Y* p, D d, A a);
 
    // observers
    element_type* get() const noexcept;
    T& operator*() const noexcept;
    T* operator->() const noexcept;
    element_type& operator[](ptrdiff_t i) const;
    long use_count() const noexcept;
    explicit operator bool() const noexcept;
    template<class U>
    bool owner_before(const shared_ptr<U>& b) const noexcept;
    template<class U>
    bool owner_before(const weak_ptr<U>& b) const noexcept;
    size_t owner_hash() const noexcept;
    template<class U>
    bool owner_equal(const shared_ptr<U>& b) const noexcept;
    template<class U>
    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>;
}

Class template std::weak_ptr

namespace std {
  template<class T>
  class weak_ptr
  {
  public:
    using element_type = remove_extent_t<T>;
 
    // constructors
    constexpr weak_ptr() noexcept;
    template<class Y>
    weak_ptr(const shared_ptr<Y>& r) noexcept;
    weak_ptr(const weak_ptr& r) noexcept;
    template<class Y>
    weak_ptr(const weak_ptr<Y>& r) noexcept;
    weak_ptr(weak_ptr&& r) noexcept;
    template<class Y>
    weak_ptr(weak_ptr<Y>&& r) noexcept;
 
    // destructor
    ~weak_ptr();
 
    // assignment
    weak_ptr& operator=(const weak_ptr& r) noexcept;
    template<class Y>
    weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
    template<class Y>
    weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    weak_ptr& operator=(weak_ptr&& r) noexcept;
    template<class Y>
    weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
 
    // modifiers
    void swap(weak_ptr& r) noexcept;
    void reset() noexcept;
 
    // observers
    long use_count() const noexcept;
    bool expired() const noexcept;
    shared_ptr<T> lock() const noexcept;
    template<class U>
    bool owner_before(const shared_ptr<U>& b) const noexcept;
    template<class U>
    bool owner_before(const weak_ptr<U>& b) const noexcept;
    size_t owner_hash() const noexcept;
    template<class U>
    bool owner_equal(const shared_ptr<U>& b) const noexcept;
    template<class U>
    bool owner_equal(const weak_ptr<U>& b) const noexcept;
  };
 
  template<class T>
  weak_ptr(shared_ptr<T>) -> weak_ptr<T>;
}

Class template std::owner_less

namespace std {
  template<class T = void>
  struct owner_less;
 
  template<class T>
  struct owner_less<shared_ptr<T>>
  {
    bool operator()(const shared_ptr<T>&, const shared_ptr<T>&) const noexcept;
    bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept;
    bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept;
  };
 
  template<class T>
  struct owner_less<weak_ptr<T>>
  {
    bool operator()(const weak_ptr<T>&, const weak_ptr<T>&) const noexcept;
    bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept;
    bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept;
  };
 
  template<>
  struct owner_less<void>
  {
    template<class T, class U>
    bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept;
    template<class T, class U>
    bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept;
    template<class T, class U>
    bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept;
    template<class T, class U>
    bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept;
 
    using is_transparent = /* unspecified */;
  };
}

Class std::owner_hash

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 = /* unspecified */;
  };
}

Class std::owner_equal

namespace std {
  struct owner_equal
  {
    template<class T, class U>
    bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept;
    template<class T, class U>
    bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept;
    template<class T, class U>
    bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept;
    template<class T, class U>
    bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept;
 
    using is_transparent = /* unspecified */;
  };
}

Class template std::enable_shared_from_this

namespace std {
  template<class T>
  class enable_shared_from_this
  {
  protected:
    constexpr enable_shared_from_this() noexcept;
    enable_shared_from_this(const enable_shared_from_this&) noexcept;
    enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept;
    ~enable_shared_from_this();
 
  public:
    shared_ptr<T> shared_from_this();
    shared_ptr<T const> shared_from_this() const;
    weak_ptr<T> weak_from_this() noexcept;
    weak_ptr<T const> weak_from_this() const noexcept;
 
  private:
    mutable weak_ptr<T> /*weak-this*/; // exposition-only
  };
}

Class template std::atomic's specialization for std::shared_ptr

namespace std {
  template<class T> struct atomic<shared_ptr<T>> {
    using value_type = shared_ptr<T>;
    static constexpr bool is_always_lock_free = /* implementation-defined */;
 
    bool is_lock_free() const noexcept;
    void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
    shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
    operator shared_ptr<T>() const noexcept;
 
    shared_ptr<T> exchange(shared_ptr<T> desired,
                           memory_order order = memory_order::seq_cst) noexcept;
 
    bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
                               memory_order success, memory_order failure) noexcept;
    bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
                                 memory_order success, memory_order failure) noexcept;
 
    bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
                               memory_order order = memory_order::seq_cst) noexcept;
    bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
                                 memory_order order = memory_order::seq_cst) noexcept;
 
    constexpr atomic() noexcept = default;
    atomic(shared_ptr<T> desired) noexcept;
    atomic(const atomic&) = delete;
    void operator=(const atomic&) = delete;
    void operator=(shared_ptr<T> desired) noexcept;
 
  private:
    shared_ptr<T> p;            // exposition only
  };
}

Class template std::atomic's specialization for std::weak_ptr

namespace std {
  template<class T> struct atomic<weak_ptr<T>> {
    using value_type = weak_ptr<T>;
    static constexpr bool is_always_lock_free = /* implementation-defined */;
 
    bool is_lock_free() const noexcept;
    void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
    weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
    operator weak_ptr<T>() const noexcept;
 
    weak_ptr<T> exchange(weak_ptr<T> desired,
                         memory_order order = memory_order::seq_cst) noexcept;
 
    bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
                               memory_order success, memory_order failure) noexcept;
    bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
                                 memory_order success, memory_order failure) noexcept;
 
    bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
                               memory_order order = memory_order::seq_cst) noexcept;
    bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
                                 memory_order order = memory_order::seq_cst) noexcept;
 
    constexpr atomic() noexcept = default;
    atomic(weak_ptr<T> desired) noexcept;
    atomic(const atomic&) = delete;
    void operator=(const atomic&) = delete;
    void operator=(weak_ptr<T> desired) noexcept;
 
  private:
    weak_ptr<T> p;              // exposition only
  };
}

Class template std::out_ptr_t

namespace std {
  template<class Smart, class Pointer, class... Args>
  class out_ptr_t
  {
  public:
    explicit out_ptr_t(Smart&, Args...);
    out_ptr_t(const out_ptr_t&) = delete;
 
    ~out_ptr_t();
 
    operator Pointer*() const noexcept;
    operator void**() const noexcept;
 
  private:
    Smart& s;         // exposition-only
    tuple<Args...> a; // exposition-only
    Pointer p;        // exposition-only
  };
}

Class template std::inout_ptr_t

namespace std {
  template<class Smart, class Pointer, class... Args>
  class inout_ptr_t
  {
  public:
    explicit inout_ptr_t(Smart&, Args...);
    inout_ptr_t(const inout_ptr_t&) = delete;
 
    ~inout_ptr_t();
 
    operator Pointer*() const noexcept;
    operator void**() const noexcept;
 
  private:
    Smart& s;         // exposition-only
    tuple<Args...> a; // exposition-only
    Pointer p;        // exposition-only
  };
}

Class template std::indirect

namespace std {
  template<class T, class Allocator = allocator<T>>
  class indirect
  {
  public:
    using value_type     = T;
    using allocator_type = Allocator;
    using pointer        = typename allocator_traits<Allocator>::pointer;
    using const_pointer  = typename allocator_traits<Allocator>::const_pointer;
 
    // 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(/* see description */);
    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);
 
    // destructor
    constexpr ~indirect();
 
    // assignment
    constexpr indirect& operator=(const indirect& other);
    constexpr indirect& operator=(indirect&& other) noexcept(/* see description */);
    template<class U = T>
    constexpr indirect& operator=(U&& u);
 
    // 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;
 
    // swap
    constexpr void swap(indirect& other) noexcept(/* see description */);
    friend constexpr void swap(indirect& lhs,
                               indirect& rhs) noexcept(/* see description */);
 
    // relational operators
    template<class U, class AA>
    friend constexpr bool operator==(
      const indirect& lhs,
      const indirect<U, AA>& rhs) noexcept(/* see description */);
    template<class U, class AA>
    friend constexpr auto operator<=>(const indirect& lhs, const indirect<U, AA>& rhs)
      -> /*synth-three-way-result*/<T, U>;
 
    // comparison with T
    template<class U>
    friend constexpr bool operator==(const indirect& lhs,
                                     const U& rhs) noexcept(/* see description */);
    template<class U>
    friend constexpr auto operator<=>(const indirect& lhs, const U& rhs)
      -> /*synth-three-way-result*/<T, U>;
 
  private:
    pointer /*p*/;                     // exposition-only
    Allocator /*alloc*/ = Allocator(); // exposition-only
  };
  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>>;
}

Class template std::polymorphic

namespace std {
  template<class T, class Allocator = allocator<T>>
  class polymorphic
  {
  public:
    using value_type     = T;
    using allocator_type = Allocator;
    using pointer        = typename allocator_traits<Allocator>::pointer;
    using const_pointer  = typename allocator_traits<Allocator>::const_pointer;
 
    // 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(/* see description */);
    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);
 
    // destructor
    constexpr ~polymorphic();
 
    // assignment
    constexpr polymorphic& operator=(const polymorphic& other);
    constexpr polymorphic& operator=(polymorphic&& other) noexcept(/* see description */);
 
    // 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;
 
    // swap
    constexpr void swap(polymorphic& other) noexcept(/* see description */);
    friend constexpr void swap(polymorphic& lhs,
                               polymorphic& rhs) noexcept(/* see description */);
 
  private:
    Allocator /*alloc*/ = Allocator(); // exposition-only
  };
}