将std :: array与初始化列表一起使用

Chr*_*s_F 54 c++ libstdc++ c++11

除非我弄错了,否则应该可以通过以下方式创建一个std:array:

std::array<std::string, 2> strings = { "a", "b" };
std::array<std::string, 2> strings({ "a", "b" });
Run Code Online (Sandbox Code Playgroud)

然而,使用GCC 4.6.1我无法使其中任何一个工作.编译器简单地说:

expected primary-expression before ',' token
Run Code Online (Sandbox Code Playgroud)

然而初始化列表与std :: vector一起工作正常.那是哪个呢?我错误地认为std :: array应该接受初始化列表,还是让GNU标准C++库团队搞错了?

Nic*_*las 88

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

template<typename T, int size>
struct std::array
{
  T a[size];
};
Run Code Online (Sandbox Code Playgroud)

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

std::array<std::string, 2> strings = {{ "a", "b" }};
Run Code Online (Sandbox Code Playgroud)

请注意,该标准确实表明在这种情况下可以省略额外的括号.所以它可能是一个GCC错误.

  • @PaulManta:因为它不符合聚合初始化的条件.聚合初始化可以在编译时折叠,具体取决于数组元素的类型(std :: string不符合条件).无论数组元素的类型如何,初始化列表初始化*必须是运行时函数调用. (6认同)
  • 好的,所以我在维基百科http://en.wikipedia.org/wiki/Array_%28C%2B%2B%29#Implementation_as_aggregate上找到了这个.注意它是如何说的*注意,对于标准的符合性编译器,可以使用更少的大括号(根据标准的8.5.1(11))*.所以看起来GNU团队有点傻了,**应该能够将std :: array初始化为std :: array <std :: string,2> strings = {"a","b"}; (4认同)
  • @Dani:不一定是"故意的".这只是事情必须发挥作用的必要结果.`std :: array`旨在成为编译时类型,因此需要使用聚合初始化. (2认同)

Jos*_*eph 11

要添加到接受的答案:

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'}};
Run Code Online (Sandbox Code Playgroud)

所有工作都在GCC 4.6.3(Xubuntu 12.01)上进行.然而,

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

//f({'a', 'b'}); //doesn't compile
f({{'a', 'b'}});
Run Code Online (Sandbox Code Playgroud)

以上需要双括号来编译.带有单个大括号的版本会导致以下错误:

../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>’
Run Code Online (Sandbox Code Playgroud)

我不确定类型推断/转换的哪个方面使得事情以这种方式工作,或者这是否是GCC实现的怪癖.