Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 350
bluescarni Avatar asked Jul 25 '13 16:07

bluescarni


2 Answers

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), ...);
like image 116
Howard Hinnant Avatar answered Oct 16 '22 16:10

Howard Hinnant


Starting with C++20, there is std::to_address, proposed in P0653.

like image 24
Acorn Avatar answered Oct 16 '22 17:10

Acorn