From what I read in http://en.cppreference.com/w/cpp/memory/allocator , most features of the allocators are now going to be deprecated. The question is, how is one supposed to use allocators in new code? What is the "right" way now?
From what I deduce in the documentation, construct
is part of the allocator traits, rather than the allocator itself.
I am building a custom container, here it is a very simple version of the constructor, is this a good usage of the new design?
container::container(std::size_t size, T const& value, Allocator const& allocator) : allocator_(allocator){
data_ = std::allocator_traits<Alloc>::allocate(allocator_, size);
for(auto ptr = data_; ptr != data_ + size; ++ptr){
std::allocator_traits<Allocator>::construct(allocator_, ptr, value)
}
}
I tried to use an algorithm (like std::for_each
) in the loop but I didn't manage to use one without taking addresses (operator&
).
Where can I find a complete example of a modern allocator?
After some tweaking, I found a way to use an algorithm instead of the the raw loop (to which an execution policy can be passed). I am not very sure, but it could be this:
data_ = std::allocator_traits<Allocator>::allocate(allocator_, size);
std::for_each([policy? deduced from allocator?,]
boost::make_counting_iterator(data_),
boost::make_counting_iterator(data_ + size),
[&](auto ptr){std::allocator_traits<Allocator>::construct(allocator_, ptr, value);}
);
Struct std::alloc::System The default memory allocator provided by the operating system. This is based on malloc on Unix platforms and HeapAlloc on Windows, plus related functions.
Allocators handle all the requests for allocation and deallocation of memory for a given container. The C++ Standard Library provides general-purpose allocators that are used by default, however, custom allocators may also be supplied by the programmer.
std::allocator 's construct and destroy are deprecated because they are useless: no good C++11 and later code should ever call them directly, and they add nothing over the default. Handling memory alignment should be the task of allocate , not construct .
std::allocator is used when you want to separate allocation and do construction in two steps. It is also used when separate destruction and deallocation is done in two steps. All the STL containers in C++ have a type parameter Allocator that is by default std::allocator.
Yes, the current approach is through std::allocator_traits
. You'll be able to support the "minimal allocator interface" that way.
http://en.cppreference.com/w/cpp/concept/Allocator
Some requirements are optional: the template
std::allocator_traits
supplies the default implementations for all optional requirements, and all standard library containers and other allocator-aware classes access the allocator throughstd::allocator_traits
, not directly.
If you observe the std::allocator_traits
member functions and typedefs, you'll see they're detecting the presence of appropriate function/types and dispatching through them if they can.
The deprecation and potential future removal will change nothing if you're already using std::allocator_traits
since it only applies to std::allocator
and their member functions/typedefs.
Now, if you ask me, there's nothing wrong with for-loops, and using std::for_each
gains you nothing. There are several uninitialized_*
functions, but they use placement new directly. If you really care you can extract this code to a separate construct_range
function.
There's also an exception safety issue - in case one of the constructors throws, you need to destroy the earlier elements in order to satisfy the strong exception guarantee and free the memory too (destructor won't get called in case constructor throws)
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