为什么size不是std :: initializer_list的模板参数?

时间:2011-08-18 13:45:39

标签: c++ c++11 initializer-list

std::initializer_list由编译器从大括号括起的init列表构造,此列表的大小必须是编译时常量。

那么为什么委员会决定从模板参数中省略大小?这可能会阻止一些优化并使某些事情变得不可能(从std::array初始化std::initializer_list)。

2 个答案:

答案 0 :(得分:14)

如果initializer_list被定义为std::initializer_list<type, size>,则任何带有initializer_list<type>函数,其中type是某种具体类型,现在必须是基于该列表大小的模板函数。或者他们必须要求用户传递特定类型和大小initializer_list

这两个都是非常不可接受的。并非所有人都将所有代码都写为模板。

您可以从braced-init-list(std::array初始化{},其中包含中间的内容。但这与std::intiializer_list不同。 array类是聚合类型。它是一个包含单个元素的结构,它是一个公共数组。因此,在符合C ++ 11的实现上,这应该编译:

std::array<int, 3> myArray = {1, 3, 5};

但是,{1, 3, 5}不是std::initializer_list对象;它只是一个braced-init-list,可以用来初始化合适的类型。

您无法将std::initializer_list对象传递给aggegate的构造函数(因为聚合没有构造函数),但您可以使用braced-init-list调用聚合初始化来初始化std::array,就像你对任何包含数组的结构一样。

std::initializer_list和braced-init-list之间的差异有点像int和文字0之间的差异。将int对象隐式转换为指针类型并不(通常)合法,但将整数文字0隐式转换为指针类型是合法的。 braced-init-lists的工作方式是这样的:

int i = 0;    //Legal
void *j = 0;  //Legal
void *k = i;  //Not legal

std::array<int, 3> myArray = {1, 3, 5};             //Legal
std::initializer_list<int> myInitList = {1, 3, 5};  //Legal
std::array<int, 3> myArray = myInitList;            //Not legal

答案 1 :(得分:7)

现有系统的一个优点是您可以导出从DLL中获取initializer_list的函数。如果按尺寸模板化,则必须将它们作为来源运输。