Short form: We propose to add library functions that allow the systematic use of allocators as a customisation point for dynamic allocations. The new functions complete the following picture:
using operator {new,delete} | using allocator | |
|---|---|---|
| Manual | T * p = new T(args...) | auto p = allocate_new<T>(alloc, args...) |
delete p | allocate_delete(alloc, p) | |
| Unique pointer | make_unique<T>(args...) | allocate_unique<T>(alloc, args...) |
default_delete<T> | allocator_delete<T> | |
| Shared pointer | make_shared<T>(args...) | allocate_shared<T>(alloc, args...) |
Long form: The standard library rarely uses
new/delete directly, but instead allows customisation of dynamic
allocation and object construction via allocators. Currently this customisation is only
available for container elements and for shared_ptr (as well as for
a few other types that require dynamically allocated memory), but not for the top-level
objects themselves.
The proposal is to complete the library facilities for
allocator-based customisation by providing a direct mechanism for creating and destroying
a dynamically stored object through an allocator, as well as a new deleter type for
unique_ptr to hold an allocator-managed unique pointee, together with the
appropriate factory function.
std::allocate_unique<std::vector<T,
ScopedArenaAlloc<T>>>(arena_alloc) allows this. (Here we assume the
use of the usual alias idiom template <typename T> using ScopedArenaAlloc =
std::scoped_allocator_adaptor<ArenaAlloc<T>>;).auto p =
std::allocate_new<std::vector<T,
ScopedShmemAlloc<T>>>(shmem_alloc). The returned pointer is
presumably an offset pointer, and its offset value needs to be communicated to the other
participating processes. The last process to use the container calls
allocate_delete(shmem_alloc, p).To allow std::unique_ptr to use custom allocators, we first need a deleter template that stores the allocator:
The factory function is:
The type T must not be an array type.
noexcept).allocate_new take an explicit typename T
as a parameter, or use A::value_type?allocate_delete for both for the function
template that replaces delete and for the class template that replaces
default_delete to keep using the word “allocate” consistently.
That would require saying the unwieldy struct allocate_delete in the
allocate_unique function template, though.