342 lines
13 KiB
Markdown
342 lines
13 KiB
Markdown
[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.1 General"))
|
||
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.2 Allocator 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.2 Constructors"), 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.3 Member 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.2 Uses-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)
|