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

С++ 11 предоставляет класс std::allocator_traits как стандартный способ использования распределителей. Статическая функция std::allocator_traits::construct() принимает указатель на то, где должен строиться объект. Статическая функция std::allocator_traits::allocate(), однако, возвращает значение allocator::pointer, которое должно вести себя как указатель, но оно не обязательно одно (в общем случае, хотя std::allocator::pointer требуется, чтобы указатель).

Как предполагается использовать статические методы распределения и построения, если, в общем, они будут работать с несовместимыми типами? Могут ли они использоваться, только если тип pointer фактически конвертируется в обычный обычный указатель?

Ответ 1

Есть два способа сделать это в зависимости от того, что у вас есть на данный момент.

Если у вас есть выражение lvalue, скажите поле значения в node, вы можете использовать std:: addressof следующим образом:

allocator_traits<allocator_type>::construct(alloc, std::addressof(ptr->value), ...);

где ptr является allocator_type::pointer.

Однако, если у вас нет поля для разыменования и вы хотите преобразовать allocator_type::pointer в T*, вам нужно сначала выполнить трюк:

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;
}

И теперь вы можете сказать:

allocator_traits<allocator_type>::construct(alloc, to_raw_pointer(ptr), ...);