allocator_traits::construct() vs allocator_traits::allocate()

c++, c++11, memory-management

Solution

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), ...);

Problem

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?

Original source