C++11 provides the std::allocator_traits
class as the standard way to use allocators. The static function std::allocator_traits::construct()
takes a pointer to where the object should be constructed. The std::allocator_traits::allocate()
static function, however, returns an allocator::pointer
value, which only has to behave like a pointer but it is not necessarily one (in general, although std::allocator::pointer
is required to be a pointer).
How is one supposed to use the allocation and construction static methods if, in general, they will work with incompatible types? Can they be used only if the pointer
type is actually convertible to a normal plain pointer?
There are two techniques to do this depending on what you have at the moment.
If you have an lvalue expression, say the value field in a node, then you can use std::addressof like so:
allocator_traits<allocator_type>::construct(alloc, std::addressof(ptr->value), ...);
where ptr
is an allocator_type::pointer
.
However if you don't have a field to dereference and you want to convert an allocator_type::pointer
to T*
, there's a trick you need to implement first:
template <class T>
inline
T*
to_raw_pointer(T* p) noexcept
{
return p;
}
template <class Pointer>
inline
typename std::pointer_traits<Pointer>::element_type*
to_raw_pointer(Pointer p) noexcept
{
return p != nullptr ? ::to_raw_pointer(p.operator->())
: nullptr;
}
And now you can say:
allocator_traits<allocator_type>::construct(alloc, to_raw_pointer(ptr), ...);
Starting with C++20, there is std::to_address
, proposed in P0653.
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