Как точно имитировать новый T [n] с помощью распределителя?

Выражение new T[n] может или не может инициализировать каждый объект в массиве, в зависимости от того, что T.

Как воспроизвести это поведение инициализации с помощью allocator?

struct Foo
{
    int x;
    Foo() : x(1)
        { }
};

Foo *p = new Foo[1];
assert(p[0].x == 1);

Ответ 1

В С++ 03 интерфейс распределителя знает только один способ инициализации объектов, а другой - для копирования с другого объекта. С++ 11 имеет больше.

Вы запрашиваете инициализацию по умолчанию, что означает (приблизительно), "либо ничего не делать, либо вызвать конструктор по умолчанию". Интерфейс распределителя не может выполнять последний в С++ 03.

Я полагаю, вы могли бы написать что-то вроде:

T *ra = allocator.allocate(1);
if (!is_pod<T>::value) {
    // in C++03
    allocator.construct(ra, T());
    // in C++11
    allocator.construct(ra);
}

Тем не менее, тест is_pod может быть неправильным. Проверьте стандарт на то, какие условия инициализации по умолчанию ничего не делает. Очевидно, что is_pod не существует в С++ 03, но я смутно помню, что Boost имеет что-то вроде того, что работает на большинстве реализаций.

Я думаю, что вы сражаетесь с дизайном здесь. Интерфейс распределителя был разработан для использования контейнерами. Контейнеры были сконструированы так, чтобы не содержать неинициализированные элементы, поэтому они не могут использоваться для инициализации по умолчанию.