2011-11-19 139 views
46

除非我错了,应该是可以创建一个std:阵列在以下方面:使用std ::数组初始化列表

std::array<std::string, 2> strings = { "a", "b" }; 
std::array<std::string, 2> strings({ "a", "b" }); 

然而,使用GCC 4.6.1,我无法得到任何这些工作。编译器只是说:

expected primary-expression before ',' token 

然而初始化列表工作正常与std :: vector。那它是哪一个?我误以为std :: array应该接受初始化列表,还是让GNU标准C++库团队疯狂?

+0

坠毁铛...... – Dani

+0

我不知道这是否应该工作(我不掌握最新的0X的东西),但是,错误或不,我认为这是因为使用了'性病: :字符串与字符串文字。你有没有尝试用'std :: string()'包装字符串文字? –

+0

@Chris:这适用于Mac OSX 10.6上的gcc 4.6.1。你使用什么编译器选项? – juanchopanza

回答

72

std::array是有趣的。它基本上是这样定义的:

template<typename T, int size> 
struct std::array 
{ 
    T a[size]; 
}; 

它是一个包含数组的结构。它没有一个带初始化列表的构造函数。但std::array是由C++ 11的规则聚合而成的,因此它可以通过聚合初始化来创建。要聚合初始化内部阵列的结构,需要第二组花括号:

std::array<std::string, 2> strings = {{ "a", "b" }}; 

注意,标准确实表明额外的支撑可以在这种情况下被省略。所以它可能是一个GCC错误。

+0

标准委员会是否故意这样做? – Dani

+0

为什么标准不要求'std :: array'有一个可以与初始化列表一起工作的构造函数? –

+6

@PaulManta:因为那样它就不符合聚合初始化的条件。根据数组元素的类型(std :: string不符合条件),汇总初始化可以在编译时折叠。无论数组元素的类型如何,初始化程序列表初始化* must *都是运行时函数调用。 –

9

要添加到接受的答案:

std::array<char, 2> a1{'a', 'b'}; 
std::array<char, 2> a2 = {'a', 'b'}; 
std::array<char, 2> a3{{'a', 'b'}}; 
std::array<char, 2> a4 = {{'a', 'b'}}; 

在GCC 4.6.3(Xubuntu上12.01)的所有工作。然而,

void f(std::array<char, 2> a) 
{ 
} 

//f({'a', 'b'}); //doesn't compile 
f({{'a', 'b'}}); 

以上需要双大括号来编译。在下面的错误单括号结果版本:

../src/main.cc: In function ‘int main(int, char**)’: 
../src/main.cc:23:17: error: could not convert ‘{'a', 'b'}’ from ‘<brace-enclosed initializer list>’ to ‘std::array<char, 2ul>’ 

我不知道哪方面类型推断/转换使事情以这种方式工作,或者如果这是GCC的实现的怪癖。