Files
2025-10-25 03:02:53 +03:00

342 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[mem.poly.allocator.class]
# 20 Memory management library [[mem]](./#mem)
## 20.5 Memory resources [[mem.res]](mem.res#mem.poly.allocator.class)
### 20.5.3 Class template polymorphic_allocator [mem.poly.allocator.class]
#### [20.5.3.1](#general) General [[mem.poly.allocator.class.general]](mem.poly.allocator.class.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7653)
A specialization of class template pmr::polymorphic_allocator meets
the *Cpp17Allocator* requirements ([[allocator.requirements.general]](allocator.requirements.general "16.4.4.6.1General"))
if its template argument is a cv-unqualified object type[.](#general-1.sentence-1)
Constructed with different memory resources,
different instances of the same specialization of pmr::polymorphic_allocator can exhibit entirely different allocation behavior[.](#general-1.sentence-2)
This runtime polymorphism allows objects that use polymorphic_allocator to behave as if they used different allocator types at run time
even though they use the same static allocator type[.](#general-1.sentence-3)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7664)
A specialization of class template pmr::polymorphic_allocator meets the allocator completeness requirements ([[allocator.requirements.completeness]](allocator.requirements.completeness "16.4.4.6.2Allocator completeness requirements"))
if its template argument is a cv-unqualified object type[.](#general-2.sentence-1)
[🔗](#lib:polymorphic_allocator)
namespace std::pmr {template<class Tp = byte> class polymorphic_allocator { memory_resource* memory_rsrc; // *exposition only*public:using value_type = Tp; // [[mem.poly.allocator.ctor]](#mem.poly.allocator.ctor "20.5.3.2Constructors"), constructors polymorphic_allocator() noexcept;
polymorphic_allocator(memory_resource* r);
polymorphic_allocator(const polymorphic_allocator& other) = default; template<class U> polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
polymorphic_allocator& operator=(const polymorphic_allocator&) = delete; // [[mem.poly.allocator.mem]](#mem.poly.allocator.mem "20.5.3.3Member functions"), member functions Tp* allocate(size_t n); void deallocate(Tp* p, size_t n); void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t)); template<class T> T* allocate_object(size_t n = 1); template<class T> void deallocate_object(T* p, size_t n = 1); template<class T, class... CtorArgs> T* new_object(CtorArgs&&... ctor_args); template<class T> void delete_object(T* p); template<class T, class... Args>void construct(T* p, Args&&... args); template<class T>void destroy(T* p);
polymorphic_allocator select_on_container_copy_construction() const;
memory_resource* resource() const; // friendsfriend bool operator==(const polymorphic_allocator& a, const polymorphic_allocator& b) noexcept {return *a.resource() == *b.resource(); }};}
#### [20.5.3.2](#mem.poly.allocator.ctor) Constructors [[mem.poly.allocator.ctor]](mem.poly.allocator.ctor)
[🔗](#lib:polymorphic_allocator,constructor)
`polymorphic_allocator() noexcept;
`
[1](#mem.poly.allocator.ctor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7728)
*Effects*: Sets memory_rsrc to get_default_resource()[.](#mem.poly.allocator.ctor-1.sentence-1)
[🔗](#lib:polymorphic_allocator,constructor_)
`polymorphic_allocator(memory_resource* r);
`
[2](#mem.poly.allocator.ctor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7739)
*Preconditions*: r is non-null[.](#mem.poly.allocator.ctor-2.sentence-1)
[3](#mem.poly.allocator.ctor-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7743)
*Effects*: Sets memory_rsrc to r[.](#mem.poly.allocator.ctor-3.sentence-1)
[4](#mem.poly.allocator.ctor-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7747)
*Throws*: Nothing[.](#mem.poly.allocator.ctor-4.sentence-1)
[5](#mem.poly.allocator.ctor-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7751)
[*Note [1](#mem.poly.allocator.ctor-note-1)*:
This constructor provides an implicit conversion from memory_resource*[.](#mem.poly.allocator.ctor-5.sentence-1)
— *end note*]
[🔗](#lib:polymorphic_allocator,constructor__)
`template<class U> polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
`
[6](#mem.poly.allocator.ctor-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7763)
*Effects*: Sets memory_rsrc to other.resource()[.](#mem.poly.allocator.ctor-6.sentence-1)
#### [20.5.3.3](#mem.poly.allocator.mem) Member functions [[mem.poly.allocator.mem]](mem.poly.allocator.mem)
[🔗](#lib:allocate,polymorphic_allocator)
`Tp* allocate(size_t n);
`
[1](#mem.poly.allocator.mem-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7777)
*Effects*: If numeric_limits<size_t>::max() / sizeof(Tp) < n,
throws bad_array_new_length[.](#mem.poly.allocator.mem-1.sentence-1)
Otherwise equivalent to:return static_cast<Tp*>(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp)));
[🔗](#lib:deallocate,polymorphic_allocator)
`void deallocate(Tp* p, size_t n);
`
[2](#mem.poly.allocator.mem-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7793)
*Preconditions*: p was allocated from a memory resource x,
equal to *memory_rsrc,
using x.allocate(n * sizeof(Tp), alignof(Tp))[.](#mem.poly.allocator.mem-2.sentence-1)
[3](#mem.poly.allocator.mem-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7799)
*Effects*: Equivalent to memory_rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp))[.](#mem.poly.allocator.mem-3.sentence-1)
[4](#mem.poly.allocator.mem-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7803)
*Throws*: Nothing[.](#mem.poly.allocator.mem-4.sentence-1)
[🔗](#lib:allocate_bytes,polymorphic_allocator)
`void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t));
`
[5](#mem.poly.allocator.mem-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7814)
*Effects*: Equivalent to: return memory_rsrc->allocate(nbytes, alignment);
[6](#mem.poly.allocator.mem-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7818)
[*Note [1](#mem.poly.allocator.mem-note-1)*:
The return type is void* (rather than, e.g., byte*)
to support conversion to an arbitrary pointer type U* by static_cast<U*>, thus facilitating construction of a U object in the allocated memory[.](#mem.poly.allocator.mem-6.sentence-1)
— *end note*]
[🔗](#lib:deallocate_bytes,polymorphic_allocator)
`void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t));
`
[7](#mem.poly.allocator.mem-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7833)
*Effects*: Equivalent to memory_rsrc->deallocate(p, nbytes, alignment)[.](#mem.poly.allocator.mem-7.sentence-1)
[🔗](#lib:allocate_object,polymorphic_allocator)
`template<class T>
T* allocate_object(size_t n = 1);
`
[8](#mem.poly.allocator.mem-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7845)
*Effects*: Allocates memory suitable for holding
an array of n objects of type T, as follows:
- [(8.1)](#mem.poly.allocator.mem-8.1)
if numeric_limits<size_t>::max() / sizeof(T) < n,
throws bad_array_new_length,
- [(8.2)](#mem.poly.allocator.mem-8.2)
otherwise equivalent to:return static_cast<T*>(allocate_bytes(n*sizeof(T), alignof(T)));
[9](#mem.poly.allocator.mem-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7860)
[*Note [2](#mem.poly.allocator.mem-note-2)*:
T is not deduced and must therefore be provided as a template argument[.](#mem.poly.allocator.mem-9.sentence-1)
— *end note*]
[🔗](#lib:deallocate_object,polymorphic_allocator)
`template<class T>
void deallocate_object(T* p, size_t n = 1);
`
[10](#mem.poly.allocator.mem-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7873)
*Effects*: Equivalent to deallocate_bytes(p, n*sizeof(T), alignof(T))[.](#mem.poly.allocator.mem-10.sentence-1)
[🔗](#lib:new_object,polymorphic_allocator)
`template<class T, class... CtorArgs>
T* new_object(CtorArgs&&... ctor_args);
`
[11](#mem.poly.allocator.mem-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7885)
*Effects*: Allocates and constructs an object of type T, as follows[.](#mem.poly.allocator.mem-11.sentence-1)
Equivalent to:T* p = allocate_object<T>();try { construct(p, std::forward<CtorArgs>(ctor_args)...);} catch (...) { deallocate_object(p); throw;}return p;
[12](#mem.poly.allocator.mem-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7900)
[*Note [3](#mem.poly.allocator.mem-note-3)*:
T is not deduced and must therefore be provided as a template argument[.](#mem.poly.allocator.mem-12.sentence-1)
— *end note*]
[🔗](#lib:new_object,polymorphic_allocator_)
`template<class T>
void delete_object(T* p);
`
[13](#mem.poly.allocator.mem-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7913)
*Effects*: Equivalent to:destroy(p);
deallocate_object(p);
[🔗](#lib:construct,polymorphic_allocator)
`template<class T, class... Args>
void construct(T* p, Args&&... args);
`
[14](#mem.poly.allocator.mem-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7929)
*Mandates*: Uses-allocator construction of T with allocator *this (see [[allocator.uses.construction]](allocator.uses.construction "20.2.8.2Uses-allocator construction"))
and constructor arguments std::forward<Args>(args)... is well-formed[.](#mem.poly.allocator.mem-14.sentence-1)
[15](#mem.poly.allocator.mem-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7935)
*Effects*: Constructs a T object in the storage
whose address is represented by p by uses-allocator construction with allocator *this and constructor arguments std::forward<Args>(args)...[.](#mem.poly.allocator.mem-15.sentence-1)
[16](#mem.poly.allocator.mem-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7942)
*Throws*: Nothing unless the constructor for T throws[.](#mem.poly.allocator.mem-16.sentence-1)
[🔗](#lib:destroy,polymorphic_allocator)
`template<class T>
void destroy(T* p);
`
[17](#mem.poly.allocator.mem-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7954)
*Effects*: Equivalent to p->~T()[.](#mem.poly.allocator.mem-17.sentence-1)
[🔗](#lib:select_on_container_copy_construction,polymorphic_allocator)
`polymorphic_allocator select_on_container_copy_construction() const;
`
[18](#mem.poly.allocator.mem-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7965)
*Returns*: polymorphic_allocator()[.](#mem.poly.allocator.mem-18.sentence-1)
[19](#mem.poly.allocator.mem-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7969)
[*Note [4](#mem.poly.allocator.mem-note-4)*:
The memory resource is not propagated[.](#mem.poly.allocator.mem-19.sentence-1)
— *end note*]
[🔗](#lib:resource,polymorphic_allocator)
`memory_resource* resource() const;
`
[20](#mem.poly.allocator.mem-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7981)
*Returns*: memory_rsrc[.](#mem.poly.allocator.mem-20.sentence-1)
#### [20.5.3.4](#mem.poly.allocator.eq) Equality [[mem.poly.allocator.eq]](mem.poly.allocator.eq)
[🔗](#lib:operator==,polymorphic_allocator)
`template<class T1, class T2>
bool operator==(const polymorphic_allocator<T1>& a,
const polymorphic_allocator<T2>& b) noexcept;
`
[1](#mem.poly.allocator.eq-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7996)
*Returns*: *a.resource() == *b.resource()[.](#mem.poly.allocator.eq-1.sentence-1)