I am trying to write an allocator-aware container. Suppose I want to allocate a chunk of memory for three objects:
T* chunk = std::allocator_traits<Allocator>::allocate(allocator, 3);
(I know that allocators can have custom pointer types and therefore I should use std::allocator_traits<Allocator>::pointer
; I am using raw pointers here for simplicity.)
Now I want to create an actual object at index 2. How do I do that? In particular, how do I calculate the pointer to the not-yet-existing element? The most obvious option would be the following:
std::allocator_traits<Allocator>::construct(allocator, chunk + 2, ...);
Unfortunately, chunk + 2
does not appear to be correct: according to the standard, pointer arithmetic can only be performed on pointers to array elements, and otherwise it causes undefined behavior. For the same reason, I cannot convert the pointer to std::byte*
and use pointer arithmetic on that. (While std::allocator
is defined to create an array in newly allocated memory, until C++20, the same requirement does not exist for custom allocators. Also, while C++20 adds some language for “implicit creation of objects”, this does not apply for earlier C++ versions.)
So how do I calculate the pointer to give as the second argument to construct
without causing undefined behavior (before C++20)?
In the latest standard draft (C++20):
[tab:cpp17.allocator]
a.allocate(n) - Memory is allocated for an array of n T and such an object is created but array elements are not constructed.
allocator_traits::allocate(n)
simply calls a.allocate(n)
.
So, given that the array is created, the pointer arithmetic is well defined.
In C++17 before the acceptance of proposal P0593R6, the wording was:
Memory is allocated for n objects of type T is created but objects are not constructed.
Prior to this change there was no well-defined way to do what you are asking unless:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With