Массив выровненной структуры, которая индуцирует регулярный массив отдельных членов

Если у меня есть структура (например, 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>{};

и это может сработать. Но это много ручной работы, и она может измениться, когда я изменю систему, добавлю новых участников и т. Д.

Есть ли более автоматический способ сделать это? или некоторые соглашения, чтобы следовать, чтобы сделать эту проблему менее болезненной

0 ответов

Другие вопросы по тегам