我想实现一个编译时间常数大小的数据结构(如std::array
)。我希望能够像这样初始化这个数据结构:
MyStruct<3, int> example = {1, 2, 3};
使用类似于MyStruct(std::initializer_list<T> elements)
的构造函数可以正常工作,但编译器对我的内部结构和elements
强制执行相同的大小,即使它们在编译时都是已知的。
我无法使用static_assert
,因为elements.size()
不是编译时常量。
有没有办法在编译时强制执行与elements
MyStruct
相同的{{1}}?
答案 0 :(得分:2)
您可以尝试使用可变参数模板的构造函数:
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,因为支撑省略,并不总是如an official defect report中所述那样适用。
答案 1 :(得分:1)
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}}分配给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
的数组。