Пользовательский распределитель для std :: vector & lt; char & gt; игнорируется

Я пытался использовать собственный распределитель для std::vector<char>но я заметил что std::vector не требует / не использует какие-либо функции-члены из моего распределителя. Как это возможно?

#include <vector>

struct A : private std::allocator<char> {
typedef std::allocator<char> alloc;
using alloc::value_type;
using alloc::pointer;
using alloc::const_pointer;
using alloc::difference_type;
using alloc::size_type;
using alloc::rebind;
// member functions have been removed, since the program compiles without them
};

int main() {
std::vector<char, A> v;
v.resize(4000);
for (auto& c : v)
if (c)
return 1; // never happens in my environment
return 0; // all elements initialized to 0. How is this possible?
}

Я пробовал вышеупомянутую программу с онлайн-компилятором C ++ 11 (LiveWorkSpace), предоставляя g ++ 4.7.2, 4.8 и 4.6.3.

В принципе allocate(), deallocate(), construct() а также destroy() не определены в моем распределителе, но программа компилируется, и все элементы будут инициализированы в 0.

10

Решение

Стандартная библиотека GCC всегда перепривязывает предоставленный распределитель, поэтому внутри она делает что-то вроде этого (в C ++ 03):

typedef Alloc::template rebind<value_type>::other _Allocator_type;

(В C ++ 11 он использует allocator_traits но в этом случае результат тот же.)

Затем вектор хранит объект этого типа внутри и использует его для всего (де) выделения.

Так как вы не определили rebind шаблон члена в вашем распределителе, вы только что повторно объявили шаблон из базового класса, результат повторного связывания std::allocator<value_type> а не ваш собственный тип. std::allocator конечно, предоставляет все эти функции, так что именно они используются, независимо от того, определяете ли вы их по своему типу.

Вы можете исправить это, добавив это к вашему распределителю intead of using alloc::rebind; чтобы vector хранит и использует A внутренне:

struct A : private std::allocator<char> {
template<typename U>
struct rebind {
typedef A other;
};

Нотабене это будет работать только для vector, так как vector Строго не нужно перепривязывать распределитель (пользователи должны создавать экземпляр шаблона с помощью allocator<value_type>, но GCC vector в любом случае перепривязывает, так что если пользователи создают vector<int, std::allocator<char>> это все еще работает.) Для основанных на узле контейнеров, таких как std::set ваш распределитель должен быть шаблоном, который может быть восстановлен, потому что контейнер должен распределять свои внутренние типы узлов, а не value_typeтак нужно Alloc::rebind<internal_node_type>::other быть действительным.

14

Другие решения

vector свяжет распределитель Как вы приведете его в сферу из std::allocator, A::rebind<T>::other будет просто std::allocator<T>, Так что все работает отлично.

7

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector