Выравнивание статического массива с помощью 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.