20 Memory management library [mem] (original) (raw)
20.2 Memory [memory]
20.2.1 General [memory.general]
20.2.2 Header synopsis [memory.syn]
20.2.3 Pointer traits [pointer.traits]
20.2.3.1 General [pointer.traits.general]
20.2.3.2 Member types [pointer.traits.types]
20.2.3.3 Member functions [pointer.traits.functions]
20.2.3.4 Optional members [pointer.traits.optmem]
20.2.4 Pointer conversion [pointer.conversion]
20.2.5 Pointer alignment [ptr.align]
20.2.6 Explicit lifetime management [obj.lifetime]
20.2.7 Allocator argument tag [allocator.tag]
20.2.8 uses_allocator [allocator.uses]
20.2.8.1 uses_allocator trait [allocator.uses.trait]
20.2.8.2 Uses-allocator construction [allocator.uses.construction]
20.2.9 Allocator traits [allocator.traits]
20.2.9.1 General [allocator.traits.general]
20.2.9.2 Member types [allocator.traits.types]
20.2.9.3 Static member functions [allocator.traits.members]
20.2.9.4 Other [allocator.traits.other]
20.2.10 The default allocator [default.allocator]
20.2.10.1 General [default.allocator.general]
20.2.10.2 Members [allocator.members]
20.2.10.3 Operators [allocator.globals]
20.2.11 addressof [specialized.addressof]
20.2.12 C library memory allocation [c.malloc]
20.2.1 General [memory.general]
Subclause [memory] describes the contents of the header and some of the contents of the header .
20.2.2 Header synopsis [memory.syn]
The header defines several types and function templates that describe properties of pointers and pointer-like types, manage memory for containers and other template types, destroy objects, and construct objects in uninitialized memory buffers ([pointer.traits]–[specialized.addressof] and [specialized.algorithms]).
The header also defines the templatesunique_ptr, shared_ptr, weak_ptr,out_ptr_t, inout_ptr_t, and various function templates that operate on objects of these types ([smartptr]).
Let POINTER_OF(T) denote a type that is
- T::pointer if the qualified-id T::pointeris valid and denotes a type,
- otherwise, T::element_type*if the qualified-id T::element_typeis valid and denotes a type,
- otherwise, pointer_traits<T>::element_type*.
Let POINTER_OF_OR(T, U) denote a type that is:
- POINTER_OF(T)if POINTER_OF(T) is valid and denotes a type,
- otherwise, U.
#include <compare> namespace std { template<class Ptr> struct pointer_traits; template<class T> struct pointer_traits<T*>; template<class T> constexpr T* to_address(T* p) noexcept; template<class Ptr> constexpr auto to_address(const Ptr& p) noexcept; void* align(size_t alignment, size_t size, void*& ptr, size_t& space); template<size_t N, class T> constexpr T* assume_aligned(T* ptr); template<size_t Alignment, class T> bool is_sufficiently_aligned(T* ptr);template<class T> T* start_lifetime_as(void* p) noexcept; template<class T> const T* start_lifetime_as(const void* p) noexcept; template<class T> volatile T* start_lifetime_as(volatile void* p) noexcept; template<class T> const volatile T* start_lifetime_as(const volatile void* p) noexcept; template<class T> T* start_lifetime_as_array(void* p, size_t n) noexcept; template<class T> const T* start_lifetime_as_array(const void* p, size_t n) noexcept; template<class T> volatile T* start_lifetime_as_array(volatile void* p, size_t n) noexcept; template<class T> const volatile T* start_lifetime_as_array(const volatile void* p, size_t n) noexcept;template<class T> T* trivially_relocate(T* first, T* last, T* result); template<class T> constexpr T* relocate(T* first, T* last, T* result); struct allocator_arg_t { explicit allocator_arg_t() = default; }; inline constexpr allocator_arg_t allocator_arg{}; template<class T, class Alloc> struct uses_allocator; template<class T, class Alloc> constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value; template<class T, class Alloc, class... Args> constexpr auto uses_allocator_construction_args(const Alloc& alloc, Args&&... args) noexcept;template<class T, class Alloc, class Tuple1, class Tuple2> constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, Tuple1&& x, Tuple2&& y) noexcept;template<class T, class Alloc> constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u, V&& v) noexcept;template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>& pr) noexcept;template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair<U, V>& pr) noexcept;template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>&& pr) noexcept;template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair<U, V>&& pr) noexcept;template<class T, class Alloc, pair-like P> constexpr auto uses_allocator_construction_args(const Alloc& alloc, P&& p) noexcept;template<class T, class Alloc, class U> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept;template<class T, class Alloc, class... Args> constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); template<class T, class Alloc, class... Args> constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args);template<class Alloc> struct allocator_traits; template<class Pointer, class SizeType = size_t> struct allocation_result { Pointer ptr; SizeType count;};template<class T> class allocator;template<class T, class U> constexpr bool operator==(const allocator<T>&, const allocator<U>&) noexcept;template<class T> constexpr T* addressof(T& r) noexcept; template<class T> const T* addressof(const T&&) = delete; template<class I> concept nothrow-input-iterator = see below; template<class I> concept nothrow-forward-iterator = see below; template<class I> concept nothrow-bidirectional-iterator = see below; template<class I> concept nothrow-random-access-iterator = see below; template<class S, class I> concept nothrow-sentinel-for = see below; template<class S, class I> concept nothrow-sized-sentinel-for = see below; template<class R> concept nothrow-input-range = see below; template<class R> concept nothrow-forward-range = see below; template<class R> concept nothrow-bidirectional-range = see below; template<class R> concept nothrow-random-access-range = see below; template<class R> concept nothrow-sized-random-access-range = see below; template<class NoThrowForwardIterator> constexpr void uninitialized_default_construct(NoThrowForwardIterator first, NoThrowForwardIterator last);template<class ExecutionPolicy, class NoThrowForwardIterator> void uninitialized_default_construct(ExecutionPolicy&& exec, NoThrowForwardIterator first, NoThrowForwardIterator last);template<class NoThrowForwardIterator, class Size> constexpr NoThrowForwardIterator uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); template<class ExecutionPolicy, class NoThrowForwardIterator, class Size> NoThrowForwardIterator uninitialized_default_construct_n(ExecutionPolicy&& exec, NoThrowForwardIterator first, Size n);namespace ranges { template<nothrow-forward-iterator I, nothrow-sentinel-for<I> S> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_default_construct(I first, S last); template<nothrow-forward-range R> requires default_initializable<range_value_t<R>> constexpr borrowed_iterator_t<R> uninitialized_default_construct(R&& r); template<nothrow-forward-iterator I> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_default_construct_n(I first, iter_difference_t<I> n);template<execution-policy Ep, nothrow-random-access-iterator I,nothrow-sized-sentinel-for<I> S> requires default_initializable<iter_value_t<I>> I uninitialized_default_construct(Ep&& exec, I first, S last); template<execution-policy Ep, nothrow-sized-random-access-range R> requires default_initializable<range_value_t<R>> borrowed_iterator_t<R> uninitialized_default_construct(Ep&& exec, R&& r); template<execution-policy Ep, nothrow-random-access-iterator I> requires default_initializable<iter_value_t<I>> I uninitialized_default_construct_n(Ep&& exec, I first, iter_difference_t<I> n); } template<class NoThrowForwardIterator> constexpr void uninitialized_value_construct(NoThrowForwardIterator first, NoThrowForwardIterator last);template<class ExecutionPolicy, class NoThrowForwardIterator> void uninitialized_value_construct(ExecutionPolicy&& exec, NoThrowForwardIterator first, NoThrowForwardIterator last);template<class NoThrowForwardIterator, class Size> constexpr NoThrowForwardIterator uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); template<class ExecutionPolicy, class NoThrowForwardIterator, class Size> NoThrowForwardIterator uninitialized_value_construct_n(ExecutionPolicy&& exec, NoThrowForwardIterator first, Size n);namespace ranges { template<nothrow-forward-iterator I, nothrow-sentinel-for<I> S> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_value_construct(I first, S last); template<nothrow-forward-range R> requires default_initializable<range_value_t<R>> constexpr borrowed_iterator_t<R> uninitialized_value_construct(R&& r); template<nothrow-forward-iterator I> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_value_construct_n(I first, iter_difference_t<I> n);template<execution-policy Ep, nothrow-random-access-iterator I,nothrow-sized-sentinel-for<I> S> requires default_initializable<iter_value_t<I>> I uninitialized_value_construct(Ep&& exec, I first, S last); template<execution-policy Ep, nothrow-sized-random-access-range R> requires default_initializable<range_value_t<R>> borrowed_iterator_t<R> uninitialized_value_construct(Ep&& exec, R&& r); template<execution-policy Ep, nothrow-random-access-iterator I> requires default_initializable<iter_value_t<I>> I uninitialized_value_construct_n(Ep&& exec, I first, iter_difference_t<I> n); } template<class InputIterator, class NoThrowForwardIterator> constexpr NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last, NoThrowForwardIterator result);template<class ExecutionPolicy, class ForwardIterator, class NoThrowForwardIterator> NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, NoThrowForwardIterator result);template<class InputIterator, class Size, class NoThrowForwardIterator> constexpr NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, NoThrowForwardIterator result);template<class ExecutionPolicy, class ForwardIterator, class Size,class NoThrowForwardIterator> NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, NoThrowForwardIterator result);namespace ranges { template<class I, class O> using uninitialized_copy_result = in_out_result<I, O>; template<input_iterator I, sentinel_for<I> S1,nothrow-forward-iterator O, nothrow-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); template<input_range IR, nothrow-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); template<class I, class O> using uninitialized_copy_n_result = in_out_result<I, O>; template<input_iterator I, nothrow-forward-iterator O, nothrow-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, O ofirst, S olast);template<execution-policy Ep, random_access_iterator I, sized_sentinel_for<I> S1,nothrow-random-access-iterator O, nothrow-sized-sentinel-for<O> S2> requires constructible_from<iter_value_t<O>, iter_reference_t<I>> uninitialized_copy_result<I, O> uninitialized_copy(Ep&& exec, I ifirst, S1 ilast, O ofirst, S2 olast); template<execution-policy Ep, sized-random-access-range IR,nothrow-sized-random-access-range OR> requires constructible_from<range_value_t<OR>, range_reference_t<IR>> uninitialized_copy_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>> uninitialized_copy(Ep&& exec, IR&& in_range, OR&& out_range); template<execution-policy Ep, random_access_iterator I, nothrow-random-access-iterator O,nothrow-sized-sentinel-for<O> S> requires constructible_from<iter_value_t<O>, iter_reference_t<I>> uninitialized_copy_n_result<I, O> uninitialized_copy_n(Ep&& exec, I ifirst, iter_difference_t<I> n, O ofirst, S olast); } template<class InputIterator, class NoThrowForwardIterator> constexpr NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last, NoThrowForwardIterator result);template<class ExecutionPolicy, class ForwardIterator, class NoThrowForwardIterator> NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, NoThrowForwardIterator result);template<class InputIterator, class Size, class NoThrowForwardIterator> constexpr pair<InputIterator, NoThrowForwardIterator> uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result);template<class ExecutionPolicy, class ForwardIterator, class Size,class NoThrowForwardIterator> pair<ForwardIterator, NoThrowForwardIterator> uninitialized_move_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, NoThrowForwardIterator result);namespace ranges { template<class I, class O> using uninitialized_move_result = in_out_result<I, O>; template<input_iterator I, sentinel_for<I> S1,nothrow-forward-iterator O, nothrow-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); template<input_range IR, nothrow-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); template<class I, class O> using uninitialized_move_n_result = in_out_result<I, O>; template<input_iterator I,nothrow-forward-iterator O, nothrow-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, O ofirst, S olast);template<execution-policy Ep, random_access_iterator I, sized_sentinel_for<I> S1,nothrow-random-access-iterator O, nothrow-sized-sentinel-for<O> S2> requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>> uninitialized_move_result<I, O> uninitialized_move(Ep&& exec, I ifirst, S1 ilast, O ofirst, S2 olast); template<execution-policy Ep, sized-random-access-range IR,nothrow-sized-random-access-range OR> requires constructible_from<range_value_t<OR>, range_rvalue_reference_t<IR>> uninitialized_move_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>> uninitialized_move(Ep&& exec, IR&& in_range, OR&& out_range); template<execution-policy Ep, random_access_iterator I,nothrow-random-access-iterator O, nothrow-sized-sentinel-for<O> S> requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>> uninitialized_move_n_result<I, O> uninitialized_move_n(Ep&& exec, I ifirst, iter_difference_t<I> n, O ofirst, S olast); } template<class NoThrowForwardIterator, class T> constexpr void uninitialized_fill(NoThrowForwardIterator first, NoThrowForwardIterator last, const T& x);template<class ExecutionPolicy, class NoThrowForwardIterator, class T> void uninitialized_fill(ExecutionPolicy&& exec, NoThrowForwardIterator first, NoThrowForwardIterator last,const T& x);template<class NoThrowForwardIterator, class Size, class T> constexpr NoThrowForwardIterator uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); template<class ExecutionPolicy, class NoThrowForwardIterator, class Size, class T> NoThrowForwardIterator uninitialized_fill_n(ExecutionPolicy&& exec, NoThrowForwardIterator first, Size n, const T& x);namespace ranges { template<nothrow-forward-iterator I, nothrow-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); template<nothrow-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); template<nothrow-forward-iterator I, class T> requires constructible_from<iter_value_t<I>, const T&> constexpr I uninitialized_fill_n(I first, iter_difference_t<I> n, const T& x);template<execution-policy Ep, nothrow-random-access-iterator I,nothrow-sized-sentinel-for<I> S, class T> requires constructible_from<iter_value_t<I>, const T&> I uninitialized_fill(Ep&& exec, I first, S last, const T& x); template<execution-policy Ep, nothrow-sized-random-access-range R, class T> requires constructible_from<range_value_t<R>, const T&> borrowed_iterator_t<R> uninitialized_fill(Ep&& exec, R&& r, const T& x); template<execution-policy Ep, nothrow-random-access-iterator I, class T> requires constructible_from<iter_value_t<I>, const T&> I uninitialized_fill_n(Ep&& exec, I first, iter_difference_t<I> n, const T& x); } template<class T, class... Args> constexpr T* construct_at(T* location, Args&&... args); namespace ranges { template<class T, class... Args> constexpr T* construct_at(T* location, Args&&... args); } template<class T> constexpr void destroy_at(T* location); template<class NoThrowForwardIterator> constexpr void destroy(NoThrowForwardIterator first, NoThrowForwardIterator last);template<class ExecutionPolicy, class NoThrowForwardIterator> void destroy(ExecutionPolicy&& exec, NoThrowForwardIterator first, NoThrowForwardIterator last);template<class NoThrowForwardIterator, class Size> constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, Size n);template<class ExecutionPolicy, class NoThrowForwardIterator, class Size> NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec, NoThrowForwardIterator first, Size n); namespace ranges { template<destructible T> constexpr void destroy_at(T* location) noexcept; template<nothrow-input-iterator I, nothrow-sentinel-for<I> S> requires destructible<iter_value_t<I>> constexpr I destroy(I first, S last) noexcept; template<nothrow-input-range R> requires destructible<range_value_t<R>> constexpr borrowed_iterator_t<R> destroy(R&& r) noexcept; template<nothrow-input-iterator I> requires destructible<iter_value_t<I>> constexpr I destroy_n(I first, iter_difference_t<I> n) noexcept; template<execution-policy Ep, nothrow-random-access-iterator I,nothrow-sized-sentinel-for<I> S> requires destructible<iter_value_t<I>> I destroy(Ep&& exec, I first, S last) noexcept; template<execution-policy Ep, nothrow-sized-random-access-range R> requires destructible<range_value_t<R>> borrowed_iterator_t<R> destroy(Ep&& exec, R&& r) noexcept; template<execution-policy Ep, nothrow-random-access-iterator I> requires destructible<iter_value_t<I>> I destroy_n(Ep&& exec, I first, iter_difference_t<I> n) noexcept; } 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> constexpr unique_ptr<T> make_unique(Args&&... args); template<class T> constexpr unique_ptr<T> make_unique(size_t n); template<class T, class... Args> unspecified make_unique(Args&&...) = delete; template<class T> constexpr unique_ptr<T> make_unique_for_overwrite(); template<class T> constexpr unique_ptr<T> make_unique_for_overwrite(size_t n); template<class T, class... Args> unspecified make_unique_for_overwrite(Args&&...) = delete; template<class T, class D> constexpr void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept; template<class T1, class D1, class T2, class D2> constexpr bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);template<class T1, class D1, class T2, class D2> constexpr bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);template<class T1, class D1, class T2, class D2> constexpr bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);template<class T1, class D1, class T2, class D2> constexpr bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);template<class T1, class D1, class T2, class D2> constexpr bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);template<class T1, class D1, class T2, class D2> requires three_way_comparable_with<typename unique_ptr<T1, D1>::pointer,typename unique_ptr<T2, D2>::pointer> constexpr compare_three_way_result_t<typename unique_ptr<T1, D1>::pointer,typename unique_ptr<T2, D2>::pointer> operator<=>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T, class D> constexpr bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept; template<class T, class D> constexpr bool operator<(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator<(nullptr_t, const unique_ptr<T, D>& y); template<class T, class D> constexpr bool operator>(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator>(nullptr_t, const unique_ptr<T, D>& y); template<class T, class D> constexpr bool operator<=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator<=(nullptr_t, const unique_ptr<T, D>& y); template<class T, class D> constexpr bool operator>=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator>=(nullptr_t, const unique_ptr<T, D>& y); 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); 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;template<class T> class shared_ptr;template<class T, class... Args> constexpr shared_ptr<T> make_shared(Args&&... args); template<class T, class A, class... Args> constexpr shared_ptr<T> allocate_shared(const A& a, Args&&... args); template<class T> constexpr shared_ptr<T> make_shared(size_t N); template<class T, class A> constexpr shared_ptr<T> allocate_shared(const A& a, size_t N); template<class T> constexpr shared_ptr<T> make_shared(); template<class T, class A> constexpr shared_ptr<T> allocate_shared(const A& a); template<class T> constexpr shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); template<class T, class A> constexpr shared_ptr<T> allocate_shared(const A& a, size_t N,const remove_extent_t<T>& u); template<class T> constexpr shared_ptr<T> make_shared(const remove_extent_t<T>& u); template<class T, class A> constexpr shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& u);template<class T> constexpr shared_ptr<T> make_shared_for_overwrite(); template<class T, class A> constexpr shared_ptr<T> allocate_shared_for_overwrite(const A& a); template<class T> constexpr shared_ptr<T> make_shared_for_overwrite(size_t N); template<class T, class A> constexpr shared_ptr<T> allocate_shared_for_overwrite(const A& a, size_t N); template<class T, class U> constexpr bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;template<class T, class U> constexpr strong_ordering operator<=>(const shared_ptr<T>& a,const shared_ptr<U>& b) noexcept;template<class T> constexpr bool operator==(const shared_ptr<T>& x, nullptr_t) noexcept;template<class T> constexpr strong_ordering operator<=>(const shared_ptr<T>& x, nullptr_t) noexcept;template<class T> constexpr void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;template<class T, class U> constexpr shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;template<class T, class U> constexpr shared_ptr<T> static_pointer_cast(shared_ptr<U>&& r) noexcept;template<class T, class U> constexpr shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;template<class T, class U> constexpr shared_ptr<T> dynamic_pointer_cast(shared_ptr<U>&& r) noexcept;template<class T, class U> constexpr shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;template<class T, class U> constexpr shared_ptr<T> const_pointer_cast(shared_ptr<U>&& r) noexcept;template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U>&& r) noexcept;template<class D, class T> constexpr D* get_deleter(const shared_ptr<T>& p) noexcept;template<class E, class T, class Y> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const shared_ptr<Y>& p);template<class T> class weak_ptr;template<class T> constexpr void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;template<class T = void> struct owner_less;struct owner_hash;struct owner_equal;template<class T> class enable_shared_from_this;template<class T> struct hash; template<class T, class D> struct hash<unique_ptr<T, D>>; template<class T> struct hash<shared_ptr<T>>;template<class T> struct atomic; template<class T> struct atomic<shared_ptr<T>>;template<class T> struct atomic<weak_ptr<T>>;template<class Smart, class Pointer, class... Args> class out_ptr_t; template<class Pointer = void, class Smart, class... Args> constexpr auto out_ptr(Smart& s, Args&&... args); template<class Smart, class Pointer, class... Args> class inout_ptr_t; template<class Pointer = void, class Smart, class... Args> constexpr auto inout_ptr(Smart& s, Args&&... args); template<class T, class Allocator = allocator<T>> class indirect;template<class T, class Alloc> struct hash<indirect<T, Alloc>>;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>>;} }
20.2.3 Pointer traits [pointer.traits]
20.2.3.1 General [pointer.traits.general]
The class template pointer_traits supplies a uniform interface to certain attributes of pointer-like types.
namespace std { template<class Ptr> struct pointer_traits { see below;};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.2.3.2 Member types [pointer.traits.types]
The definitions in this subclause make use of the following exposition-only class template and concept:template<class T> struct ptr-traits-elem { };template<class T> requires requires { typename T::element_type; } struct ptr-traits-elem<T> { using type = T::element_type; };template<template<class...> class SomePointer, class T, class... Args> requires (!requires { typename SomePointer<T, Args...>::element_type; }) struct ptr-traits-elem<SomePointer<T, Args...>> { using type = T; };template<class Ptr> concept has-elem-type = requires { typename ptr-traits-elem<Ptr>::type; }
If Ptr satisfies has-elem-type, a specialization pointer_traits<Ptr>generated from the pointer_traits primary template has the following members as well as those described in [pointer.traits.functions]; otherwise, such a specialization has no members by any of those names.
using pointer = _see below_;
using element_type = _see below_;
Type: typename ptr-traits-elem<Ptr>::type.
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> ifPtr is a class template instantiation of the form SomePointer<T, Args>, where Args is zero or more type arguments; otherwise, the instantiation ofrebind is ill-formed.
20.2.3.3 Member functions [pointer.traits.functions]
static pointer pointer_traits::pointer_to(_see below_ r);static constexpr pointer pointer_traits<T*>::pointer_to(_see below_ r) noexcept;
Mandates: For the first member function,Ptr::pointer_to(r) is well-formed.
Preconditions: For the first member function,Ptr::pointer_to(r) returns a pointer to rthrough which indirection is valid.
Returns: The first member function returns Ptr::pointer_to(r).
The second member function returns addressof(r).
Remarks: If element_type is cv void, the type ofr is unspecified; otherwise, it is element_type&.
20.2.3.4 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.
A specialization generated from the pointer_traits primary template has no member by this name.
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 1:
This function is intended to be the inverse of pointer_to.
If defined, it customizes the behavior of the non-member functionto_address ([pointer.conversion]).
— _end note_]
20.2.4 Pointer conversion [pointer.conversion]
template<class T> constexpr T* to_address(T* p) noexcept;
Mandates: T is not a function type.
template<class Ptr> constexpr auto to_address(const Ptr& p) noexcept;
Returns: pointer_traits<Ptr>::to_address(p) if that expression is well-formed (see [pointer.traits.optmem]), otherwise to_address(p.operator->()).
20.2.5 Pointer alignment [ptr.align]
void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
Preconditions:
- alignment is a power of two
- ptr represents the address of contiguous storage of at leastspace bytes
Effects: If it is possible to fit size bytes of storage aligned by alignment into the buffer pointed to byptr with length space, the function updatesptr to represent the first possible address of such storage and decreases space by the number of bytes used for alignment.
Otherwise, the function does nothing.
Returns: A null pointer if the requested aligned buffer would not fit into the available space, otherwise the adjusted value of ptr.
[Note 1:
The function updates its ptrand space arguments so that it can be called repeatedly with possibly different alignment and sizearguments for the same buffer.
— _end note_]
template<size_t N, class T> constexpr T* assume_aligned(T* ptr);
Mandates: N is a power of two.
[Note 2:
The alignment assumption on an object Xexpressed by a call to assume_alignedmight result in generation of more efficient code.
It is up to the program to ensure that the assumption actually holds.
The call does not cause the implementation to verify or enforce this.
An implementation might only make the assumption for those operations on X that access Xthrough the pointer returned by assume_aligned.
— _end note_]
template<size_t Alignment, class T> bool is_sufficiently_aligned(T* ptr);
Preconditions: p points to an object X of a type similar ([conv.qual]) to T.
Returns: true if X has alignment at least Alignment, otherwise false.
20.2.6 Explicit lifetime management [obj.lifetime]
template<class T> T* start_lifetime_as(void* p) noexcept;template<class T> const T* start_lifetime_as(const void* p) noexcept;template<class T> volatile T* start_lifetime_as(volatile void* p) noexcept;template<class T> const volatile T* start_lifetime_as(const volatile void* p) noexcept;
Preconditions: [p, (char*)p + sizeof(T)) denotes a region of allocated storage that is a subset of the region of storage reachable through ([basic.compound]) p and suitably aligned for the type T.
Effects: Implicitly creates objects ([intro.object]) within the denoted region consisting of an object a of type Twhose address is p, and objects nested within a, as follows: The object representation of _a_is the contents of the storage prior to the call to start_lifetime_as.
The value of each created object _o_of trivially copyable type ([basic.types.general]) Uis determined in the same manner as for a call to bit_cast<U>(E) ([bit.cast]), where E is an lvalue of type U denoting o, except that the storage is not accessed.
The value of any other created object is unspecified.
[Note 1:
The unspecified value can be indeterminate.
— _end note_]
Returns: A pointer to the a defined in the Effects paragraph.
template<class T> T* start_lifetime_as_array(void* p, size_t n) noexcept;template<class T> const T* start_lifetime_as_array(const void* p, size_t n) noexcept;template<class T> volatile T* start_lifetime_as_array(volatile void* p, size_t n) noexcept;template<class T> const volatile T* start_lifetime_as_array(const volatile void* p, size_t n) noexcept;
Mandates: T is a complete type.
Preconditions: p is suitably aligned for an array of T or is null.
n <= size_t(-1) / sizeof(T) is true.
If n > 0 is true, [(char*)p, (char*)p + (n * sizeof(T))) denotes a region of allocated storage that is a subset of the region of storage reachable through ([basic.compound]) p.
Effects: If n > 0 is true, equivalent tostart_lifetime_as<U>(p)where U is the type “array of n T”.
Otherwise, there are no effects.
Returns: A pointer to the first element of the created array, if any; otherwise, a pointer that compares equal to p ([expr.eq]).
template<class T> T* trivially_relocate(T* first, T* last, T* result);
Mandates: is_trivially_relocatable_v<T> && !is_const_v<T> is true.
T is not an array of unknown bound.
Preconditions:
- [first, last) is a valid range.
- [result, result + (last - first)) denotes a region of storage that is a subset of the region reachable through result ([basic.compound]) and suitably aligned for the type T.
- No element in the range [first, last) is a potentially-overlapping subobject.
Postconditions: No effect if result == first is true.
Otherwise, the range denoted by [result, result + (last - first)) contains objects (including subobjects) whose lifetime has begun and whose object representations are the original object representations of the corresponding objects in the source range [first, last) except for any parts of the object representations used by the implementation to represent type information ([intro.object]).
If any of the objects has union type, its active member is the same as that of the corresponding object in the source range.
If any of the aforementioned objects has a non-static data member of reference type, that reference refers to the same entity as does the corresponding reference in the source range.
The lifetimes of the original objects in the source range have ended.
Returns: result + (last - first).
Complexity: Linear in the length of the source range.
Remarks: The destination region of storage is considered reused ([basic.life]).
No constructors or destructors are invoked.
[Note 2:
Overlapping ranges are supported.
— _end note_]
template<class T> constexpr T* relocate(T* first, T* last, T* result);
Mandates: is_nothrow_relocatable_v<T> && !is_const_v<T> is true.
T is not an array of unknown bound.
Preconditions:
- [first, last) is a valid range.
- [result, result + (last - first)) denotes a region of storage that is a subset of the region reachable through result ([basic.compound]) and suitably aligned for the type T.
- No element in the range [first, last) is a potentially-overlapping subobject.
Effects:
- If result == first is true, no effect;
- otherwise, if not called during constant evaluation andis_trivially_relocatable_v<T> is true, then has effects equivalent to: trivially_relocate(first, last, result);
- otherwise, for each integer i in [0, last - first),
- if T is an array type, equivalent to:relocate(begin(first[i]), end(first[i]), *start_lifetime_as<T>(result + i));
- otherwise, equivalent to:construct_at(result + i, std::move(first[i])); destroy_at(first + i);
Returns: result + (last - first).
[Note 3:
Overlapping ranges are supported.
— _end note_]
20.2.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 (seetuple [tuple]) have constructors with allocator_arg_t as the first argument, immediately followed by an argument of a type that meets theCpp17Allocator requirements ([allocator.requirements.general]).
20.2.8 uses_allocator [allocator.uses]
20.2.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.
The implementation shall provide a definition that is derived from true_type if the qualified-id T::allocator_typeis valid and denotes a type ([temp.deduct]) andis_convertible_v<Alloc, T::allocator_type> != false, otherwise it shall be derived from false_type.
A program may specialize this template to derive fromtrue_type for a program-defined type T that does not have a nestedallocator_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.2.8.2 Uses-allocator construction [allocator.uses.construction]
Uses-allocator constructionwith allocator alloc and constructor arguments args...refers to the construction of an object of type Tsuch that alloc is passed to the constructor of Tif 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 expressionmake_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 asT(allocator_arg, alloc, args...) (leading-allocator convention), then uses-allocator construction chooses this constructor form.
- Otherwise, if T has a constructor invocable asT(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 pairsuch that uses-allocator construction is applied individually to the first and second data members.
The make_obj_using_allocator anduninitialized_construct_using_allocator function templates apply the modified constructor arguments to construct an object of type Tas a return value or in-place, respectively.
[Note 1:
For uses_allocator_construction_args andmake_obj_using_allocator, type Tis not deduced and must therefore be specified explicitly by the caller.
— _end note_]
template<class T, class Alloc, class... Args> constexpr auto uses_allocator_construction_args(const Alloc& alloc, Args&&... args) noexcept;
Constraints: remove_cv_t<T> is not a specialization of pair.
Returns: A tuple value determined as follows:
- If uses_allocator_v<remove_cv_t<T>, Alloc> is false andis_constructible_v<T, Args...> is true, return forward_as_tuple(std::forward<Args>(args)...).
- Otherwise, if uses_allocator_v<remove_cv_t<T>, Alloc> is true andis_constructible_v<T, allocator_arg_t, const Alloc&, Args...> is true, returntuple<allocator_arg_t, const Alloc&, Args&&...>( allocator_arg, alloc, std::forward<Args>(args)...)
- Otherwise, if uses_allocator_v<remove_cv_t<T>, Alloc> is true andis_constructible_v<T, Args..., const Alloc&> is true, return forward_as_tuple(std::forward<Args>(args)..., alloc).
- Otherwise, the program is ill-formed.
[Note 2:
This definition prevents a silent failure to pass the allocator to a constructor of a type for whichuses_allocator_v<T, Alloc> is true.
— _end note_]
template<class T, class Alloc, class Tuple1, class Tuple2> constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, Tuple1&& x, Tuple2&& y) noexcept;
Let T1 be T::first_type.
Let T2 be T::second_type.
Constraints: remove_cv_t<T> is a specialization of pair.
Effects: Equivalent to:return make_tuple( piecewise_construct, apply([&alloc](auto&&... args1) { return uses_allocator_construction_args<T1>( alloc, std::forward<decltype(args1)>(args1)...);}, std::forward<Tuple1>(x)), apply([&alloc](auto&&... args2) { return uses_allocator_construction_args<T2>( alloc, std::forward<decltype(args2)>(args2)...);}, std::forward<Tuple2>(y)));
template<class T, class Alloc> constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept;
Constraints: remove_cv_t<T> is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct, tuple<>{}, tuple<>{});
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u, V&& v) noexcept;
Constraints: remove_cv_t<T> is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(std::forward<U>(u)), forward_as_tuple(std::forward<V>(v)));
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>& pr) noexcept;template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc,const pair<U, V>& pr) noexcept;
Constraints: remove_cv_t<T> is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(pr.first), forward_as_tuple(pr.second));
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>&& pr) noexcept;template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc,const pair<U, V>&& pr) noexcept;
Constraints: remove_cv_t<T> is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(get<0>(std::move(pr))), forward_as_tuple(get<1>(std::move(pr))));
template<class T, class Alloc, [_pair-like_](tuple.syn#concept:pair-like "22.4.2 Header <tuple> synopsis [tuple.syn]") P> constexpr auto uses_allocator_construction_args(const Alloc& alloc, P&& p) noexcept;
Constraints: remove_cv_t<T> is a specialization of pair andremove_cvref_t<P> is not a specialization of ranges::subrange.
Effects: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(get<0>(std::forward<P>(p))), forward_as_tuple(get<1>(std::forward<P>(p))));
template<class T, class Alloc, class U> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept;
Let FUN be the function template:template<class A, class B> void FUN(const pair<A, B>&);
Constraints: remove_cv_t<T> is a specialization of pair, and either:
- remove_cvref_t<U> is a specialization of ranges::subrange, or
- U does not satisfy pair-like and the expression FUN(u) is not well-formed when considered as an unevaluated operand.
Let pair-constructor be an exposition-only class defined as follows:class pair-constructor { using pair-type = remove_cv_t<T>; constexpr auto do-construct(const pair-type& p) const { return make_obj_using_allocator<_pair-type_>(alloc_, p);} constexpr auto do-construct(pair-type&& p) const { return make_obj_using_allocator<_pair-type_>(alloc_, std::move(p));} const Alloc& alloc_; U& u_; public: constexpr operator pair-type() const { return do-construct(std::forward<U>(u_));} };
Returns: make_tuple(pc), where pc is a pair-constructor object whose alloc_ member is initialized with alloc and whose u_ member is initialized with u.
template<class T, class Alloc, class... Args> constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args);
Effects: Equivalent to:return make_from_tuple<T>(uses_allocator_construction_args<T>( alloc, std::forward<Args>(args)...));
template<class T, class Alloc, class... Args> constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args);
Effects: Equivalent to:return apply([&]<class... U>(U&&... xs) { return construct_at(p, std::forward<U>(xs)...);}, uses_allocator_construction_args<T>(alloc, std::forward<Args>(args)...));
20.2.9 Allocator traits [allocator.traits]
20.2.9.1 General [allocator.traits.general]
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_traitssupplies the entire required interface.
[Note 1:
Thus, it is always possible to create a derived class from an allocator.
— _end note_]
If a program declares an explicit or partial specialization of allocator_traits, the program is ill-formed, no diagnostic required.
namespace std { template<class Alloc> struct allocator_traits { using allocator_type = Alloc;using value_type = 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>>;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);};}
20.2.9.2 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]); otherwisefalse_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]); otherwisefalse_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]); otherwisefalse_type.
using is_always_equal = _see below_;
Type: Alloc::is_always_equal if the qualified-id Alloc::is_always_equalis 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.2.9.3 Static member functions [allocator.traits.members]
static constexpr pointer allocate(Alloc& a, size_type n);
static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint);
Returns: a.allocate(n, hint) if that expression is well-formed; otherwise, a.allocate(n).
static constexpr allocation_result<pointer, size_type> allocate_at_least(Alloc& a, size_type n);
Returns: a.allocate_at_least(n) if that expression is well-formed; otherwise, {a.allocate(n), n}.
static constexpr void deallocate(Alloc& a, pointer p, size_type n);
Effects: Calls a.deallocate(p, n).
template<class T, class... Args> static constexpr void construct(Alloc& a, T* p, Args&&... args);
Effects: Calls a.construct(p, std::forward<Args>(args)...)if that call is well-formed; otherwise, invokes construct_at(p, std::forward<Args>(args)...).
template<class T> static constexpr void destroy(Alloc& a, T* p);
Effects: Calls a.destroy(p) if that call is well-formed; otherwise, invokesdestroy_at(p).
static constexpr size_type max_size(const Alloc& a) noexcept;
Returns: a.max_size() if that expression is well-formed; otherwise,numeric_limits<size_type>::max() / sizeof(value_type).
static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs);
Returns: rhs.select_on_container_copy_construction() if that expression is well-formed; otherwise, rhs.
20.2.9.4 Other [allocator.traits.other]
The class template allocation_result has the template parameters, data members, and special members specified above.
It has no base classes or members other than those specified.
20.2.10 The default allocator [default.allocator]
20.2.10.1 General [default.allocator.general]
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);};}
allocator_traits<allocator<T>>::is_always_equal::valueis true for any T.
20.2.10.2 Members [allocator.members]
Except for the destructor, member functions of the default allocator shall not introduce data races ([intro.multithread]) as a result of concurrent calls to those member functions from different threads.
Calls to these functions that allocate or deallocate a particular unit of storage shall occur in a single total order, and each such deallocation call shall happen before the next allocation (if any) in this order.
constexpr T* allocate(size_t n);
Returns: A pointer to the initial element of an array of n T.
Throws: bad_array_new_length ifnumeric_limits<size_t>::max() / sizeof(T) < n, orbad_alloc if the storage cannot be obtained.
Remarks: The storage for the array is obtained by calling ::operator new ([new.delete]), but it is unspecified when or how often this function is called.
This function starts the lifetime of the array object, but not that of any of the array elements.
constexpr allocation_result<T*> allocate_at_least(size_t n);
Returns: allocation_result<T*>{ptr, count}, where ptr is a pointer to the initial element of an array of count T andcount ≥ n.
Throws: bad_array_new_lengthif numeric_limits<size_t>::max() / sizeof(T) < n, or bad_alloc if the storage cannot be obtained.
Remarks: The storage for the array is obtained by calling ::operator new, but it is unspecified when or how often this function is called.
This function starts the lifetime of the array object, but not that of any of the array elements.
constexpr void deallocate(T* p, size_t n);
Preconditions:
- If p is memory that was obtained by a call to allocate_at_least, let ret be the value returned andreq be the value passed as the first argument to that call.
p is equal to ret.ptr andn is a value such that req ≤ n ≤ ret.count. - Otherwise, p is a pointer value obtained from allocate.
n equals the value passed as the first argument to the invocation of allocate which returned p.
Effects: Deallocates the storage referenced by p.
Remarks: Uses::operator delete ([new.delete]), but it is unspecified when this function is called.
20.2.10.3 Operators [allocator.globals]
template<class T, class U> constexpr bool operator==(const allocator<T>&, const allocator<U>&) noexcept;
20.2.11 addressof [specialized.addressof]
template<class T> constexpr T* addressof(T& r) noexcept;
Returns: The actual address of the object or function referenced by r, even in the presence of an overloaded operator&.
Remarks: An expression addressof(E)is a constant subexpression ([defns.const.subexpr]) if E is an lvalue constant subexpression.
20.2.12 C library memory allocation [c.malloc]
[Note 1:
The header 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);
Effects: These functions have the semantics specified in the C standard library.
Remarks: These functions do not attempt to allocate storage by calling ::operator new() ([new.delete]).
These functions implicitly create objects ([intro.object]) in the returned region of storage and return a pointer to a suitable created object.
In the case of calloc, the objects are created before the storage is zeroed.
void* realloc(void* ptr, size_t size);
Preconditions: free(ptr) has well-defined behavior.
Effects: If ptr is not null and size is zero, the behavior is erroneous and the effects are implementation-defined.
Otherwise, this function has the semantics specified in the C standard library.
Remarks: This function does not attempt to allocate storage by calling ::operator new() ([new.delete]).
When a non-null pointer is returned, this function implicitly creates objects ([intro.object]) in the returned region of storage and returns a pointer to a suitable created object.
The objects are created before the storage is copied.
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/IEC 9899:2024, 7.24.4