[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 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 polymorphic_allocator(const polymorphic_allocator& 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 T* allocate_object(size_t n = 1); template void deallocate_object(T* p, size_t n = 1); template T* new_object(CtorArgs&&... ctor_args); template void delete_object(T* p); templatevoid construct(T* p, Args&&... args); templatevoid 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 polymorphic_allocator(const polymorphic_allocator& 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​::​max() / sizeof(Tp) < n, throws bad_array_new_length[.](#mem.poly.allocator.mem-1.sentence-1) Otherwise equivalent to:return static_cast(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, 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 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​::​max() / sizeof(T) < n, throws bad_array_new_length, - [(8.2)](#mem.poly.allocator.mem-8.2) otherwise equivalent to:return static_cast(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 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 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();try { construct(p, std::forward(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 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 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)... 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)...[.](#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 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 bool operator==(const polymorphic_allocator& a, const polymorphic_allocator& 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)