20 General utilities library [utilities]

20.10 Memory [memory]

20.10.1 In general [memory.general]

This subclause describes the contents of the header <memory> and some of the contents of the header <cstdlib>.

20.10.2 Header <memory> synopsis [memory.syn]

The header <memory> defines several types and function templates that describe properties of pointers and pointer-like types, manage memory for containers and other template types, destroy objects, and construct multiple objects in uninitialized memory buffers ([pointer.traits][specialized.algorithms]).
The header also defines the templates unique_­ptr, shared_­ptr, weak_­ptr, and various function templates that operate on objects of these types ([smartptr]).
namespace std {
  // [pointer.traits], pointer traits
  template<class Ptr> struct pointer_traits;
  template<class T> struct pointer_traits<T*>;

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

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

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

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

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

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

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

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

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

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

  template<class T>
    constexpr T* addressof(T& r) noexcept;
  template<class T>
    const T* addressof(const T&&) = delete;
  template<class ForwardIterator>
    void uninitialized_default_construct(ForwardIterator first, ForwardIterator last);
  template<class ExecutionPolicy, class ForwardIterator>
    void uninitialized_default_construct(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads]
                                         ForwardIterator first, ForwardIterator last);
  template<class ForwardIterator, class Size>
    ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n);
  template<class ExecutionPolicy, class ForwardIterator, class Size>
    ForwardIterator uninitialized_default_construct_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads]
                                                      ForwardIterator first, Size n);

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

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

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

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

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

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

  namespace ranges {
    template<class I, class O>
    using uninitialized_copy_result = copy_result<I, O>;
    template<InputIterator I, Sentinel<I> S1,
             no-throw-forward-iterator O, no-throw-sentinel<O> S2>
      requires Constructible<iter_value_t<O>, iter_reference_t<I>>
        uninitialized_copy_result<I, O>
          uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast);
    template<InputRange IR, no-throw-forward-range OR>
      requires Constructible<iter_value_t<iterator_t<OR>>, iter_reference_t<iterator_t<IR>>>
        uninitialized_copy_result<safe_iterator_t<IR>, safe_iterator_t<OR>>
          uninitialized_copy(IR&& input_range, OR&& output_range);

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

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

  namespace ranges {
    template<class I, class O>
      using uninitialized_move_result = uninitialized_copy_result<I, O>;
    template<InputIterator I, Sentinel<I> S1,
             no-throw-forward-iterator O, no-throw-sentinel<O> S2>
      requires Constructible<iter_value_t<O>, iter_rvalue_reference_t<I>>
        uninitialized_move_result<I, O>
          uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast);
    template<InputRange IR, no-throw-forward-range OR>
      requires Constructible<iter_value_t<iterator_t<OR>>,
                             iter_rvalue_reference_t<iterator_t<IR>>>
        uninitialized_move_result<safe_iterator_t<IR>, safe_iterator_t<OR>>
          uninitialized_move(IR&& input_range, OR&& output_range);

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

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

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

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

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

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

    template<no-throw-input-iterator I, no-throw-sentinel<I> S>
      requires Destructible<iter_value_t<I>>
        I destroy(I first, S last) noexcept;
    template<no-throw-input-range R>
      requires Destructible<iter_value_t<iterator_t<R>>
        safe_iterator_t<R> destroy(R&& r) noexcept;

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

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

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

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

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

  template<class T1, class D1, class T2, class D2>
    bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template<class T1, class D1, class T2, class D2>
    bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

  template<class T, class D>
    bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
  template<class T, class D>
    bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept;
  template<class T, class D>
    bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept;
  template<class T, class D>
    bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept;
  template<class T, class D>
    bool operator<(const unique_ptr<T, D>& x, nullptr_t);
  template<class T, class D>
    bool operator<(nullptr_t, const unique_ptr<T, D>& y);
  template<class T, class D>
    bool operator>(const unique_ptr<T, D>& x, nullptr_t);
  template<class T, class D>
    bool operator>(nullptr_t, const unique_ptr<T, D>& y);
  template<class T, class D>
    bool operator<=(const unique_ptr<T, D>& x, nullptr_t);
  template<class T, class D>
    bool operator<=(nullptr_t, const unique_ptr<T, D>& y);
  template<class T, class D>
    bool operator>=(const unique_ptr<T, D>& x, nullptr_t);
  template<class T, class D>
    bool operator>=(nullptr_t, const unique_ptr<T, D>& y);

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

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

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

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

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

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

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

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

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

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

  // [util.smartptr.shared.cmp], shared_­ptr comparisons
  template<class T, class U>
    bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    bool operator>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    bool operator<=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
  template<class T, class U>
    bool 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>
    bool operator==(nullptr_t, const shared_ptr<T>& y) noexcept;
  template<class T>
    bool operator!=(const shared_ptr<T>& x, nullptr_t) noexcept;
  template<class T>
    bool operator!=(nullptr_t, const shared_ptr<T>& y) noexcept;
  template<class T>
    bool operator<(const shared_ptr<T>& x, nullptr_t) noexcept;
  template<class T>
    bool operator<(nullptr_t, const shared_ptr<T>& y) noexcept;
  template<class T>
    bool operator>(const shared_ptr<T>& x, nullptr_t) noexcept;
  template<class T>
    bool operator>(nullptr_t, const shared_ptr<T>& y) noexcept;
  template<class T>
    bool operator<=(const shared_ptr<T>& x, nullptr_t) noexcept;
  template<class T>
    bool operator<=(nullptr_t, const shared_ptr<T>& y) noexcept;
  template<class T>
    bool operator>=(const shared_ptr<T>& x, nullptr_t) noexcept;
  template<class T>
    bool operator>=(nullptr_t, const shared_ptr<T>& y) noexcept;

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

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

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

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

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

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

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

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

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

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

20.10.3 Pointer traits [pointer.traits]

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

    template<class U> using rebind = see below;

    static pointer pointer_to(see below r);
  };

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

    template<class U> using rebind = U*;

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

20.10.3.1 Member types [pointer.traits.types]

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

20.10.3.2 Member functions [pointer.traits.functions]

static pointer pointer_traits::pointer_to(see below r); static constexpr pointer pointer_traits<T*>::pointer_to(see below r) noexcept;
Remarks: If element_­type is cv void, the type of r is unspecified; otherwise, it is element_­type&.
Returns: The first member function returns a pointer to r obtained by calling Ptr::pointer_­to(r) through which indirection is valid; an instantiation of this function is ill-formed if Ptr does not have a matching pointer_­to static member function.
The second member function returns addressof(r).

20.10.3.3 Optional members [pointer.traits.optmem]

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

20.10.4 Pointer conversion [pointer.conversion]

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

20.10.5 Pointer safety [util.dynamic.safety]

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

20.10.6 Pointer alignment [ptr.align]

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

20.10.7 Allocator argument tag [allocator.tag]

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

20.10.8 uses_­allocator [allocator.uses]

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

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

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

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

20.10.9 Allocator traits [allocator.traits]

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

    using value_type         = typename Alloc::value_type;

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

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

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

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

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

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

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

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

    static size_type max_size(const Alloc& a) noexcept;

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

20.10.9.1 Member types [allocator.traits.types]

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

20.10.9.2 Static member functions [allocator.traits.members]

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

20.10.10 The default allocator [default.allocator]

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

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

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

20.10.10.1 Members [allocator.members]

Except for the destructor, member functions of the default allocator shall not introduce data races as a result of concurrent calls to those member functions from different threads.
Calls to these functions that allocate or deallocate a particular unit of storage shall occur in a single total order, and each such deallocation call shall happen before the next allocation (if any) in this order.
[[nodiscard]] T* allocate(size_t n);
Returns: A pointer to the initial element of an array of storage of size n * sizeof(T), aligned appropriately for objects of type T.
Remarks: the storage is obtained by calling ​::​operator new, but it is unspecified when or how often this function is called.
Throws: bad_­alloc if the storage cannot be obtained.
void deallocate(T* p, size_t n);
Requires: p shall be a pointer value obtained from allocate().
n shall equal the value passed as the first argument to the invocation of allocate which returned p.
Effects: Deallocates the storage referenced by p .
Remarks: Uses ​::​operator delete, but it is unspecified when this function is called.

20.10.10.2 Operators [allocator.globals]

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

20.10.11 Specialized algorithms [specialized.algorithms]

Throughout this subclause, the names of template parameters are used to express type requirements for those algorithms defined directly in namespace std.
  • If an algorithm's template parameter is named InputIterator, the template argument shall meet the Cpp17InputIterator requirements ([input.iterators]).
  • If an algorithm's template parameter is named ForwardIterator, the template argument shall meet the Cpp17ForwardIterator requirements ([forward.iterators]), and is required to have the property that no exceptions are thrown from increment, assignment, comparison, or indirection through valid iterators.
Unless otherwise specified, if an exception is thrown in the following algorithms, objects constructed by a placement new-expression ([expr.new]) are destroyed in an unspecified order before allowing the exception to propagate.
In the description of the algorithms, operator - is used for some of the iterator categories for which it need not be defined.
In these cases, the value of the expression b - a is the number of increments of a needed to make bool(a == b) be true.
The following additional requirements apply for those algorithms defined in namespace std::ranges:
  • The entities defined in the std::ranges namespace in this subclause are not found by argument-dependent name lookup ([basic.lookup.argdep]). When found by unqualified ([basic.lookup.unqual]) name lookup for the postfix-expression in a function call ([expr.call]), they inhibit argument-dependent name lookup.
  • Overloads of algorithms that take Range arguments ([range.range]) behave as if they are implemented by calling ranges::begin and ranges::end on the Range(s) and dispatching to the overload that takes separate iterator and sentinel arguments.
  • The number and order of deducible template parameters for algorithm declarations is unspecified, except where explicitly stated otherwise.
    [Note
    : Consequently, these algorithms may not be called with explicitly-specified template argument lists. —end note
    ]
[Note
:
When invoked on ranges of potentially overlapping subobjects ([intro.object]), the algorithms specified in this subclause [specialized.algorithms] result in undefined behavior.
end note
]
Some algorithms defined in this clause make use of the exposition-only function voidify:
template<class T>
  void* voidify(T& obj) noexcept {
    return const_cast<void*>(static_cast<const volatile void*>(addressof(obj)));
  }

20.10.11.1 Special memory concepts [special.mem.concepts]

Some algorithms in this subclause are constrained with the following exposition-only concepts:
template<class I> concept no-throw-input-iterator = // exposition only InputIterator<I> && is_lvalue_reference_v<iter_reference_t<I>> && Same<remove_cvref_t<iter_reference_t<I>>, iter_value_t<I>>;
A type I models no-throw-input-iterator only if no exceptions are thrown from increment, copy construction, move construction, copy assignment, move assignment, or indirection through valid iterators.
[Note
:
This concept allows some InputIterator ([iterator.concept.input]) operations to throw exceptions.
end note
]
template<class S, class I> concept no-throw-sentinel = Sentinel<S, I>; // exposition only
Types S and I model no-throw-sentinel only if no exceptions are thrown from copy construction, move construction, copy assignment, move assignment, or comparisons between valid values of type I and S.
[Note
:
This concept allows some Sentinel ([iterator.concept.sentinel]) operations to throw exceptions.
end note
]
template<class R> concept no-throw-input-range = // exposition only Range<R> && no-throw-input-iterator<iterator_t<R>> && no-throw-sentinel<sentinel_t<R>, iterator_t<R>>;
A type R models no-throw-input-range only if no exceptions are thrown from calls to ranges::begin and ranges::end on an object of type R.
template<class I> concept no-throw-forward-iterator = // exposition only no-throw-input-iterator<I> && ForwardIterator<I> && no-throw-sentinel<I, I>;
[Note
:
This concept allows some ForwardIterator ([iterator.concept.forward]) operations to throw exceptions.
end note
]
template<class R> concept no-throw-forward-range = // exposition only no-throw-input-range<R> && no-throw-forward-iterator<iterator_t<R>>;

20.10.11.2 addressof [specialized.addressof]

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

20.10.11.3 uninitialized_­default_­construct [uninitialized.construct.default]

template<class ForwardIterator> void uninitialized_default_construct(ForwardIterator first, ForwardIterator last);
Effects: Equivalent to:
for (; first != last; ++first)
  ::new (voidify(*first))
    typename iterator_traits<ForwardIterator>::value_type;
namespace ranges { template<no-throw-forward-iterator I, no-throw-sentinel<I> S> requires DefaultConstructible<iter_value_t<I>> I uninitialized_default_construct(I first, S last); template<no-throw-forward-range R> requires DefaultConstructible<iter_value_t<iterator_t<R>>> safe_iterator_t<R> uninitialized_default_construct(R&& r); }
Effects: Equivalent to:
for (; first != last; ++first)
  ::new (voidify(*first)) remove_reference_t<iter_reference_t<I>>;
return first;
template<class ForwardIterator, class Size> ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n);
Effects: Equivalent to:
for (; n > 0; (void)++first, --n)
  ::new (voidify(*first))
    typename iterator_traits<ForwardIterator>::value_type;
return first;
namespace ranges { template<no-throw-forward-iterator I> requires DefaultConstructible<iter_value_t<I>> I uninitialized_default_construct_n(I first, iter_difference_t<I> n); }
Effects: Equivalent to:
return uninitialized_default_construct(counted_iterator(first, n),
                                       default_sentinel).base();

20.10.11.4 uninitialized_­value_­construct [uninitialized.construct.value]

template<class ForwardIterator> void uninitialized_value_construct(ForwardIterator first, ForwardIterator last);
Effects: Equivalent to:
for (; first != last; ++first)
  ::new (voidify(*first))
    typename iterator_traits<ForwardIterator>::value_type();
namespace ranges { template<no-throw-forward-iterator I, no-throw-sentinel<I> S> requires DefaultConstructible<iter_value_t<I>> I uninitialized_value_construct(I first, S last); template<no-throw-forward-range R> requires DefaultConstructible<iter_value_t<iterator_t<R>>> safe_iterator_t<R> uninitialized_value_construct(R&& r); }
Effects: Equivalent to:
for (; first != last; ++first)
  ::new (voidify(*first)) remove_reference_t<iter_reference_t<I>>();
return first;
template<class ForwardIterator, class Size> ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n);
Effects: Equivalent to:
for (; n > 0; (void)++first, --n)
  ::new (voidify(*first))
    typename iterator_traits<ForwardIterator>::value_type();
return first;
namespace ranges { template<no-throw-forward-iterator I> requires DefaultConstructible<iter_value_t<I>> I uninitialized_value_construct_n(I first, iter_difference_t<I> n); }
Effects: Equivalent to:
return uninitialized_value_construct(counted_iterator(first, n),
                                     default_sentinel).base();

20.10.11.5 uninitialized_­copy [uninitialized.copy]

template<class InputIterator, class ForwardIterator> ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result);
Expects: [result, (last - first)) shall not overlap with [first, last).
Effects: Equivalent to:
for (; first != last; ++result, (void) ++first)
  ::new (voidify(*result))
    typename iterator_traits<ForwardIterator>::value_type(*first);
Returns: result.
namespace ranges { template<InputIterator I, Sentinel<I> S1, no-throw-forward-iterator O, no-throw-sentinel<O> S2> requires Constructible<iter_value_t<O>, iter_reference_t<I>> uninitialized_copy_result<I, O> uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast); template<InputRange IR, no-throw-forward-range OR> requires Constructible<iter_value_t<iterator_t<OR>>, iter_reference_t<iterator_t<IR>>> uninitialized_copy_result<safe_iterator_t<IR>, safe_iterator_t<OR>> uninitialized_copy(IR&& input_range, OR&& output_range); }
Expects: [ofirst, olast) shall not overlap with [ifirst, ilast).
Effects: Equivalent to:
for (; ifirst != ilast && ofirst != olast; ++ofirst, (void)++ifirst) {
  ::new (voidify(*ofirst)) remove_reference_t<iter_reference_t<O>>(*ifirst);
}
return {ifirst, ofirst};
template<class InputIterator, class Size, class ForwardIterator> ForwardIterator uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result);
Expects: [result, n) shall not overlap with [first, n).
Effects: Equivalent to:
for ( ; n > 0; ++result, (void) ++first, --n) {
  ::new (voidify(*result))
    typename iterator_traits<ForwardIterator>::value_type(*first);
}
Returns: result.
namespace ranges { template<InputIterator I, no-throw-forward-iterator O, no-throw-sentinel<O> S> requires Constructible<iter_value_t<O>, iter_reference_t<I>> uninitialized_copy_n_result<I, O> uninitialized_copy_n(I ifirst, iter_difference_t<I> n, O ofirst, S olast); }
Expects: [ofirst, olast) shall not overlap with [ifirst, n).
Effects: Equivalent to:
auto t = uninitialized_copy(counted_iterator(ifirst, n),
                            default_sentinel, ofirst, olast);
return {t.in.base(), t.out};

20.10.11.6 uninitialized_­move [uninitialized.move]

template<class InputIterator, class ForwardIterator> ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result);
Expects: [result, (last - first)) shall not overlap with [first, last).
Effects: Equivalent to:
for (; first != last; (void)++result, ++first)
  ::new (voidify(*result))
    typename iterator_traits<ForwardIterator>::value_type(std::move(*first));
return result;
namespace ranges { template<InputIterator I, Sentinel<I> S1, no-throw-forward-iterator O, no-throw-sentinel<O> S2> requires Constructible<iter_value_t<O>, iter_rvalue_reference_t<I>> uninitialized_move_result<I, O> uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast); template<InputRange IR, no-throw-forward-range OR> requires Constructible<iter_value_t<iterator_t<OR>>, iter_rvalue_reference_t<iterator_t<IR>>> uninitialized_move_result<safe_iterator_t<IR>, safe_iterator_t<OR>> uninitialized_move(IR&& input_range, OR&& output_range); }
Expects: [ofirst, olast) shall not overlap with [ifirst, ilast).
Effects: Equivalent to:
for (; ifirst != ilast && ofirst != olast; ++ofirst, (void)++ifirst) {
  ::new (voidify(*ofirst))
    remove_reference_t<iter_reference_t<O>>(ranges::iter_move(ifirst));
}
return {ifirst, ofirst};
[Note
:
If an exception is thrown, some objects in the range [first, last) are left in a valid, but unspecified state.
end note
]
template<class InputIterator, class Size, class ForwardIterator> pair<InputIterator, ForwardIterator> uninitialized_move_n(InputIterator first, Size n, ForwardIterator result);
Expects: [result, n) shall not overlap with [first, n).
Effects: Equivalent to:
for (; n > 0; ++result, (void) ++first, --n)
  ::new (voidify(*result))
    typename iterator_traits<ForwardIterator>::value_type(std::move(*first));
return {first,result};
namespace ranges { template<InputIterator I, no-throw-forward-iterator O, no-throw-sentinel<O> S> requires Constructible<iter_value_t<O>, iter_rvalue_reference_t<I>> uninitialized_move_n_result<I, O> uninitialized_move_n(I ifirst, iter_difference_t<I> n, O ofirst, S olast); }
Expects: [ofirst, olast) shall not overlap with [ifirst, n).
Effects: Equivalent to:
auto t = uninitialized_move(counted_iterator(ifirst, n),
                            default_sentinel, ofirst, olast);
return {t.in.base(), t.out};
[Note
:
If an exception is thrown, some objects in the range [first, n) are left in a valid but unspecified state.
end note
]

20.10.11.7 uninitialized_­fill [uninitialized.fill]

template<class ForwardIterator, class T> void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x);
Effects: Equivalent to:
for (; first != last; ++first)
  ::new (voidify(*first))
    typename iterator_traits<ForwardIterator>::value_type(x);
namespace ranges { template<no-throw-forward-iterator I, no-throw-sentinel<I> S, class T> requires Constructible<iter_value_t<I>, const T&> I uninitialized_fill(I first, S last, const T& x); template<no-throw-forward-range R, class T> requires Constructible<iter_value_t<iterator_t<R>>, const T&> safe_iterator_t<R> uninitialized_fill(R&& r, const T& x); }
Effects: Equivalent to:
for (; first != last; ++first) {
  ::new (voidify(*first)) remove_reference_t<iter_reference_t<I>>(x);
}
return first;
template<class ForwardIterator, class Size, class T> ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x);
Effects: Equivalent to:
for (; n--; ++first)
  ::new (voidify(*first))
    typename iterator_traits<ForwardIterator>::value_type(x);
return first;
namespace ranges { template<no-throw-forward-iterator I, class T> requires Constructible<iter_value_t<I>, const T&> I uninitialized_fill_n(I first, iter_difference_t<I> n, const T& x); }
Effects: Equivalent to:
return uninitialized_fill(counted_iterator(first, n), default_sentinel, x).base();

20.10.11.8 destroy [specialized.destroy]

template<class T> void destroy_at(T* location); namespace ranges { template<Destructible T> void destroy_at(T* location) noexcept; }
Effects:
  • If T is an array type, equivalent to destroy(begin(*location), end(*location)).
  • Otherwise, equivalent to location->~T().
template<class ForwardIterator> void destroy(ForwardIterator first, ForwardIterator last);
Effects: Equivalent to:
for (; first!=last; ++first)
  destroy_at(addressof(*first));
namespace ranges { template<no-throw-input-iterator I, no-throw-sentinel<I> S> requires Destructible<iter_value_t<I>> I destroy(I first, S last) noexcept; template<no-throw-input-range R> requires Destructible<iter_value_t<iterator_t<R>>> safe_iterator_t<R> destroy(R&& r) noexcept; }
Effects: Equivalent to:
for (; first != last; ++first)
  destroy_at(addressof(*first));
return first;
template<class ForwardIterator, class Size> ForwardIterator destroy_n(ForwardIterator first, Size n);
Effects: Equivalent to:
for (; n > 0; (void)++first, --n)
  destroy_at(addressof(*first));
return first;
namespace ranges { template<no-throw-input-iterator I> requires Destructible<iter_value_t<I>> I destroy_n(I first, iter_difference_t<I> n) noexcept; }
Effects: Equivalent to:
return destroy(counted_iterator(first, n), default_sentinel).base();

20.10.12 C library memory allocation [c.malloc]

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