How can I construct my objects allocated through std::allocator::allocate()?
Asked Answered
H

2

7

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.

Hierogram answered 1/1, 2021 at 0:5 Comment(0)
A
8

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.

Documentation in cppreference

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);
Antidromic answered 1/1, 2021 at 0:40 Comment(5)
Alloc::pointer is also removed in C++20. Just use the trait throughout, or better yet auto: 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
@Mabellemable Thanks. I forgot that ::pointer was removed too.Antidromic
Also, I believe you're supposed to pass std::to_address(i) to construct, not i. construct takes a pointer; i is whatever the allocator wants it to be.Myself
Thanks. It seems to work. How am I supposed to construct multiple elements at once? Currently, Im reimplementing a vector container. I am using this static construct member function to construct 5 elements to their default value, after the user passed the vector's size.Hierogram
If you want to construct multimple elements, you will have to iterate. This is how I did it. Just look at the construction, and ignore the clean up in case the defautl construction throws, I currently in the reworks for that.Antidromic
W
2

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.

https://en.cppreference.com/w/cpp/memory/construct_at

Which answered 1/1, 2021 at 0:38 Comment(5)
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 thoughAlgorism
@Human-Compiler Equivalence for std::allocator is not that interesting in the context of using allocators. Not every allocator is std::allocator.Mabellemable
@deduplicator You appear to misunderstand; I am referring to the standard allocator concept, not 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
@Human-Compiler I was referring to your last sentence. std::construct_at is only equivalent to std::allocator_traits::construct() for std::allocator.Mabellemable
@Mabellemable Ah I see what you are getting at -- fair enoughAlgorism

© 2022 - 2024 — McMap. All rights reserved.