Выравнивание статического массива с помощью std:: выровненное хранилище
Я пытаюсь реализовать 16-байтовое выравнивание простого статического массива с помощью std:: aligned_storage шаблон:
#include <type_traits>
int main()
{
const size_t SIZE = 8;
using float_16 = std::aligned_storage<sizeof(float) * SIZE, 16>::type;
float_16 mas;
new(&mas) float[SIZE];//Placement new. Is this necessary?
mas[0]=1.f;//Compile error while attempting to set elements of aligned array
}
Я получаю следующую ошибку компиляции:
нет соответствия для "operator []" в " mas[0]"
затем я попытался использовать явное приведение типов указателей:
float* mas_ = reinterpret_cast<float*>(mas);
но это также дает ошибку компиляции:
недопустимое приведение из типа " float_16 {aka std:: aligned_storage:: type} "для ввода" float*"
может кто-нибудь предложить мне, как выровнять статический массив с помощью std:: aligned_storage правильно?
3 ответов
вы можете использовать:
float* floats = new (&mas) float[SIZE];
и тогда вы можете использовать:
floats[0] = 1.f;
нет reinterpret_cast
на всех :)
mas
не является указателем. reinterpret_cast
должны включать исключительно указатели, ссылки или интегральные типы и только в некоторых комбинациях: указатели на интегральные типы и из них, указатели на указатели, ссылки на ссылки или интегральный тип для себя. В этом случае вы пытаетесь case an std::aligned_storage<32u, 16u>::type
на указатель. Лучшее, что вы могли бы получить от этого, - это ссылка на приведение указателя, но это не разрешено†.
попробуйте вместо этого привести свой адрес к другому типу указателя: reinterpret_cast<float*>(&mas);
.
† для удовольствия: худшее, что вы могли бы получить, если бы std::aligned_storage<32u, 16u>::type
тип указателя. Это сомнительно, так как 32-байтовые указатели не являются общими, но это может произойти для std::aligned_storage<8u, 8u>::type
, например, в очень неприятной стандартной библиотеке. Назовем это адом++. Итак, в Hell++ он будет компилироваться нормально, и вы в конечном итоге приведете тип указателя к другому типу указателя, а затем сделаете все гадости на нем, как разыменование его. Это было бы катастрофой, потому что если std::aligned_storage<32u, 16u>::type
был указатель тип, объекты не будут иметь адрес для хранения, но они будут быть вместо хранения.
просто делать
alignas(16) float mas[SIZE];
std::aligned_storage
является реликвией C++03, исходящей от boost
.