如何从std::initializer_list构建类似std::array的数据结构

How to build std::array like data structure from std::initializer_list

本文关键字:std array 数据结构 构建 initializer list      更新时间:2023-10-16

我想实现一个具有编译时常量大小的数据结构(如std::array)。我希望能够像这样初始化这个数据结构:

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

使用像MyStruct(std::initializer_list<T> elements)这样的构造函数可以很好地工作,但编译器不会为我的内部结构和elements强制执行相同的大小,即使它们在编译时都是已知的。

我不能使用static_assert,因为elements.size()不是编译时间常数。

有没有办法在编译时强制elementsMyStruct的大小相同?

您可以尝试使用可变模板的构造函数:

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:arrayMyStruct之间仍然存在差异:

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,这并不总是适用于官方缺陷报告中记录的情况。

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的数组。