Массив выровненной структуры, которая индуцирует регулярный массив отдельных членов
Если у меня есть структура (например, employee
ниже), массив такой структуры индуцирует пошаговые массивы всех элементов структуры, только если размер структуры является (наименьшим) общим кратным (LCM) размера всех элементов.
В противном случае в массиве будут указатели на конкретные экземпляры-члены, которые не будут иметь интегральных расстояний указателей (измеренных в размере класса-члена).
Так, например, с учетом этой структуры:
struct employee{
std::string name;
short salary;
std::size_t age;
};
std::vector<employee> v
(или массив employee[N]
в этом отношении) вызывает широкий массив salary
члены (с шагом sizeof(employee)/sizeof(short)
) а также шаговые массивы age
,
То есть массив зарплат выбирается случайным образом &(v.data()->salary) + sizeof(employee)/sizeof(short)* n
,
Однако это не вызывает большой массив имен, потому что sizeof(employee)
(=48) не кратно sizeof(std::string)
(32) (в моей системе).
Конечно, я мог бы определить структуру другим способом, чтобы разрешить это:
struct alignas(32) employee{ // or alignas(sizeof(std::string))
std::string name;
short salary;
std::size_t age;
employee(short salary, std::size_t age) : salary{salary}, age{age}{}
};
Мне интересно, если найти это правильно alignas
Аргумент - единственный способ достичь этого. Кроме того, если есть автоматический способ получить это число без необходимости вручную находить общий множитель.
Мне кажется, что самый общий способ сделать это, не задумываясь, это сделать что-то вроде:
struct alignas(LCM(sizeof(std::string), sizeof(short), sizeof(std::size_t) ) employee{
std::string name;
short salary;
std::size_t age;
employee(short salary, std::size_t age) : salary{salary}, age{age}{}
};
То есть я должен заранее перечислить всех участников. Я мог бы использовать constexpr std::lcm
соединяя это несколько раз).
Это правильный способ сделать это?
Кроме того, всегда можно найти патологические случаи, в которых это даже не работает, потому что есть дополнительные ограничения, что выравнивание должно быть степенью 2 (в некоторых системах). В этом случае общее кратное число также должно быть степенью 2 и может ли это быть огромным числом:
using password_type = std::array<char, 103>; // suppose I cannot change the 103
struct alignas(std::lcm(std::lcm(std::lcm(sizeof(std::string), sizeof(short)), sizeof(std::size_t)), sizeof(password_type))) employee{ // bad alignment
password_type password;
std::string name;
short salary;
std::size_t age;
employee(short salary, std::size_t age) : salary{salary}, age{age}{}
};
...error: requested alignment ‘3296’ is not a positive power of 2
Чтобы выравнивание LCM работало, я должен вручную изменить выравнивание определенного элемента или добавить constexpr
потолок до ближайшей степени 2.
struct alignas(std::lcm(std::lcm(std::lcm(sizeof(std::string), sizeof(short)), sizeof(std::size_t)), 128)) employee{ // bad alignment
alignas(128) password_type password;
std::string name;
short salary;
std::size_t age;
employee(short salary, std::size_t age) : salary{salary}, age{age}{}
};
Однако это все еще не решает проблему, потому что alignas
не является частью password_type
Кажется, что единственное решение - это иметь версию std::array
это также принимает внутренний аргумент выравнивания! std::aligned_array<char, 103, 128>
,
Хорошо, я все еще могу сделать это, но за счет изменения других классов, которые не связаны с employee
первоначально.
struct alignas(128) password_type : std::array<char, 103>{};
и это может сработать. Но это много ручной работы, и она может измениться, когда я изменю систему, добавлю новых участников и т. Д.
Есть ли более автоматический способ сделать это? или некоторые соглашения, чтобы следовать, чтобы сделать эту проблему менее болезненной