reinterpret_cast, std::aligned_storage и новое размещение

Рассмотрим следующий объект:

std::array<std::aligned_storage_t<sizeof(T), alignof(T)>, size> container;

Если я уже назвал размещение нового для первого элемента этого массива, я считаю вполне приемлемым сделать следующее:

reinterpret_cast<T *>(container.data());

Это связано с тем, что data() возвращает указатель на базовый массив, который также можно рассматривать как указатель на первый элемент этого базового массива. Я разместил объект в этом месте с помощью размещения new, поэтому в этом месте находится объект типа T.

Обратите внимание, что здесь должно быть допустимо reinterpret_cast, а не цепочка static_cast, см. static_cast и реинтерпретировать_каст для std::aligned_storage.

Однако что, если я на самом деле не назвал размещение новым? Законно ли мне создавать этот указатель, если я не разыменовываю его?

Моей мотивацией здесь является реализация std::vector-подобного класса, поддерживаемого статическим массивом (поэтому без косвенного или динамического распределения). Я пытаюсь реализовать функцию-член data(). Удобно иметь всегда действующий способ с нулевыми издержками для создания пары указатели + размер, которые представляют данные: data(), size(). Поскольку size() вернет 0, в итоге я создаю указатель, который никогда не разыменовываю.


person David Stone    schedule 05.09.2015    source источник
comment
Да, reinterpret_cast сам по себе безопасен.   -  person T.C.    schedule 05.09.2015
comment
Почему бы не использовать пользовательский распределитель с уже существующим std::vector и не использовать распределитель в стеке, используя параметр шаблона размера? Но в любом случае, просто делать гипс безопасно.   -  person Brandon    schedule 05.09.2015
comment
@Brandon: Это тратит не менее sizeof(void *) * 2 места для указателей внутри вектора. Это также приводит к тому, что все мои обращения проходят через указатели, а непрямой доступ может убить конвейерную обработку, в зависимости от того, насколько легко компилятор/процессор может это увидеть, и это то, что оптимизаторы не всегда хорошо делают. Я почти исключительно выполняю работу, в которой пространство накладных расходов равно времени накладных расходов.   -  person David Stone    schedule 05.09.2015
comment
However, what if I have not actually called placement new? Is it legal for me to construct this pointer, as long as I do not dereference it? [basic.life]/5 До того, как началось время жизни объекта, но после того, как хранилище, которое будет занимать объект, было выделено ... любой указатель, ссылающийся на место хранения, в котором объект будет быть ... расположенным может использоваться, но только ограниченными способами ... Далее в параграфе подробно описываются эти способы. Все будет хорошо, пока вы остаетесь в этих пределах.   -  person Igor Tandetnik    schedule 05.09.2015
comment
@IgorTandetnik: Сделай это ответом, и я приму его   -  person David Stone    schedule 06.09.2015