Наследование стандартного распределителя не требуется. Удалите наследство : public std::allocator<T>
, и компилятор будет любезен сообщить вам о том, что вы пропустили для реализации. До C ++ 17 метод construct
должен быть реализован, и он используется в std::vector
, а не allocate
. Также отсутствуют value_type
, deallocator
и destroy
.
template< class U, class... Args >
void construct( U* p, Args&&... args );
Так как вы не реализовали это, и ваш распределитель наследует стандартный распределитель, вызывается std::allocator::construct
, который не производит вывод ,
Почему вы не должны наследовать std :: allocator
Ответ на этот вопрос прост, с одной стороны, и непрост на практике, с другой стороны.
- Как и другие классы в стандартной библиотеке C ++,
std::allocator
не имеет виртуального деструктора, поэтому он не должен наследоваться, если он не указан явно, как в std::enable_shared_from_this
. Стандартные контейнеры don не использовать class Allocator
напрямую. Они используют std::allocator_traits
. Это помогает реализовать минимальные пользовательские распределители. Если вы реализуете только value_type
, allocate
и deallocate
членов MyAllocator
, std::allocator_traits<MyAllocator>
делает MyAllocator
полностью соответствующим C ++ названным требованиям: Allocator .
- Давайте внимательно посмотрим на ваш
MyAllocator
. Он наследует std::allocator
и «заменяет» std::allocator::allocate (2)
. - Позволяет прочитать
std::allocator_traits::allocate (2)
справочное руководство, которое вызывается std::vector
: Звонит a.allocate(n, hint)
, если это возможно. Если невозможно (например, a не имеет функции-члена allocate () с двумя аргументами), вызывает a.allocate(n)
.
То, что вы достигли. Вы реализовали MyAllocator::allocate(std::size_t n)
(2), но не MyAllocator::allocate(std::size_t n, const void* hint)
(1), он унаследован от std::allocator
. Он вызывается с std::vector
, это не то, что вы ожидали. Если бы вы не унаследовали std::allocator
, была бы вызвана ваша реализация MyAllocator::allocate
.