C++20 removed the construct()
and destruct()
members from std::allocator
. How am I supposed to construct my objects allocated through std::allocator<T>::allocate()
? I found std::uninitialized_fill()
and std::uninitialized_copy()
, but as far as I understood they are not allocator-aware, and they do copies, which I think would hurt performance a lot for non-POD types.
You can do it using std::allocator_traits
.
The point of removing the construct method is because the allocator traits already has that method, and the STL containers use std::allocator_traits::construct
anyway.
And here is a little example: (Alloc
is any allocator)
Alloc a{};
std::allocator_traits<Alloc>::pointer i = std::allocator_traits<Alloc>::allocate(a, allocated_size);
// You use the construct and destroy methods from the allocator traits
std::allocator_traits<Alloc>::construct(a, i, value_to_construt);
std::allocator_traits<Alloc>::destroy(a, i);
std::allocator_traits<Alloc>::deallocate(a, i, allocated_size);
::pointer
was removed too. –
Antidromic std::to_address(i)
to construct
, not i
. construct
takes a pointer; i
is whatever the allocator wants it to be. –
Myself It looks like a static
form of construct
still exists in C++20. Maybe that is intended to replace the original form of construct
?
https://en.cppreference.com/w/cpp/memory/allocator_traits/construct
I have not really done much with custom allocation so I don't have personal experience using these functions, but it seems reasonable that they might prefer a static function in an effort to break dependencies.
There is also a construct_at
function that is added with C++20.
allocator_traits::construct
is the correct (also backwards-compatible) answer. When writing any code consuming standard allocators, its almost always expected that functionality is used via allocator_traits
rather than the allocator type itself -- which allows for allocators to effectively be given statically defined "default" implementations of some functions (such as construct
, etc). Technically C++20 onward, construct_at
and allocator_traits::construct
would be synonymous though –
Algorism std::allocator
is not that interesting in the context of using allocators. Not every allocator is std::allocator
. –
Mabellemable std::allocator
. The expected way to interact with any allocator generically is to use allocator_traits
because certain functions or features need not be explicitly defined, and allocator_traits
provides these defaults. –
Algorism std::construct_at
is only equivalent to std::allocator_traits::construct()
for std::allocator
. –
Mabellemable © 2022 - 2024 — McMap. All rights reserved.
Alloc::pointer
is also removed in C++20. Just use the trait throughout, or better yetauto
:extern Alloc a; using AT = std::allocator_traits<Alloc>; auto p = AT::allocate(a, count); AT::construct(a, p + i, constructor_arguments); AT::destroy(a, p + i); AT::deallocate(a, p, count);
– Mabellemable