2011-08-18 131 views
17

std::initializer_list由编译器从大括号括起来的init列表构造而成,并且此列表的大小必须是编译时间常量。为什么大小不是std :: initializer_list的模板参数?

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

+4

一个非常类似的问题是: “为什么'的std :: initializer_list :: size'不'constexpr'(了)?”这是一年前在clC++ m上提出的。 – MSalters

+1

Re MSalters'2011评论,请注意,即使C++ 11没有,C++ 14 *也会使std :: initializer_list :: size成为'constexpr'函数。 http://en.cppreference.com/w/cpp/utility/initializer_list/size – Quuxplusone

回答

7

现有系统的一个优点是可以导出从DLL中取出initializer_list的函数。如果它是根据尺寸模板化的,则必须将其作为源代码进行发货。

+4

沿着同样的路线:它可能会导致一些不平凡的膨胀。 – MSalters

13

如果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的构造函数(因为聚集有没有构造函数),但你可以使用一个支撑,初始化列表来调用集合初始化,初始化std::array,就像你对任何结构包含一个数组。

std::initializer_list与加载初始化列表之间的区别有点像int和字面0之间的区别。将(int)对象隐式转换为指针类型并不是(通常)合法的,但将整数文字0隐式转换为指针类型是合法的。方式支撑-INIT-名单的工作是这样的:

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 
+0

你确定要从'std :: initializer_list'初始化'std :: array'吗? '数组 x = {1,2,3}'不适用于gcc 4.6,我不能推断这应该从n3242起作用。 – pmr

+0

@pmr:std :: array被定义(在N3291中)为一个结构体,它遵循C++ 0x规则的聚合类型。因此,它应该通过聚合初始化进行初始化。所以你初始化它,就好像它是一个持有3个元素的数组的结构。我会更新我的帖子来解释这一点。 –

+1

@Nicol:这只是聚合初始化 - 'initializer_list'是完全正交的。 – ildjarn

相关问题