Если я объявлю свой класс struct alignas(16) C { int x; };, гарантированно ли x будет выровнен по 16 байтам, или компилятор может дополнить его «слева»? А как насчет template <typename T, std::size_t Align> struct alignas(Align) Aligned : T { using T::T; };? Будет ли T из Aligned<T, N> совпадать с N? Это правильный способ сделать тип, который всегда выровнен по T?





If I declare my class
struct alignas(16) C { int x; };, isxguaranteed to be aligned to 16 bytes or could the compiler pad it on the “left”?
В этом случае x должен быть на границе 16 байт, потому что у вас есть стандартный класс компоновки. Стандартный класс макета поставляется с гарантией того, что первый член класса имеет тот же адрес, что и сам класс, что означает, что он будет иметь такое же выравнивание.
What about
template <typename T, std::size_t Align> struct alignas(Align) Aligned : T { using T::T; };?
Это тот же случай, если T является стандартным классом макета. Если это так, то Aligned имеет стандартный макет, и первый подобъект базового класса гарантированно находится в начале объекта в памяти, поэтому он имеет такое же выравнивание.
Is that the right way to make a type that is a
Tthat is always aligned?
Это способ. Другой подход — использовать объект std::aligned_storage, а затем использовать новое размещение, чтобы поместить объект в это выровненное хранилище.
Увидев ваш ответ, я понял, что не учел
template <typename T, std::size_t Algn> using Aligned = alignas(Algn) T;. Но нет, это почему-то не так: godbolt.org/z/jK8KbaT8E