Как построить std :: array как структуру данных из std :: initializer_list

Я хочу реализовать структуру данных с постоянным размером времени компиляции (например, std::array). Я хочу иметь возможность инициализировать эту структуру данных следующим образом:

MyStruct<3, int> example = {1, 2, 3};

Это прекрасно работает с использованием конструктора, как: MyStruct(std::initializer_list<T> elements), но компилятор не обеспечивает такой же размер для моей внутренней структуры и elements, даже если они оба известны во время компиляции.

Я не могу использовать static_assert так как elements.size() не является постоянной времени компиляции.

Есть ли способ обеспечить во время компиляции тот же размер для elements как в MyStruct?

3

Решение

Вы можете попробовать конструктор, используя шаблоны с переменным числом аргументов:

template<std::size_t N, typename E>
struct MyStruct {
int otherStuff;
E values[N];

template<typename ...TT>
MyStruct(TT&&...t) : values{std::forward<TT>(t)...} {
static_assert(N == sizeof...(t), "Size mismatch!");
for (size_t i = 0; i < N; i++) std::cout << values[i] << ",";
std::cout << std::endl;
}
};

Это работает как ожидалось с:

MyStruct<3, int> example = {1,2,3};
MyStruct<3, int> exampleFail = {1,2}; //error: static assertion failed: Size mismatch!

Пожалуйста, обратите внимание, что есть еще разница между std:array а также MyStruct когда дело доходит до инициализации списка:

MyStruct<3, int> exampleList{1,2,3}; // works
std::array<int, 3> arr = {1,2,3};    // works, but warning with clang++
std::array<int, 3> arrList{1,2,3};   // works with g++, does not compile with clang++

Причина в том, что одиночная фигурная скобка работает только для std :: array из-за исключения фигурной скобки, которая не всегда применяется, как описано в официальный отчет о дефектах.

2

Другие решения

std::array не имеет конструктора! И это не использует initializer_listвместо этого он использует uniform initialization, (похоже на структуры POD, на самом деле std::array является структурой POD).

И что std::array действительно очень похож на следующее:

template<int size, typename T>
struct array {
T data[size];
// and some member function here;
// Warning! No constructors !
};

Когда позже ты пишешь

std::array<3, int> arr = {1,2,3};

Это эквивалентно

std::array<3, int> arr = {{1,2,3}};

И это только инициализация POD, где {1,2,3} назначено data,


Если вы хотите обеспечить проверку одинакового размера во время компиляции, вы можете использовать std::array сам вместо std::initializer_list,

Если вы измените свои инициализации с {1,2,3} в std::array<3, int>{1, 2, 3} и аргумент конструктора из std::initializer_list<T> в std::array<SIZE, T> пользователь будет вынужден передать массив с размером SIZE,

1

По вопросам рекламы [email protected]