【问题标题】:Is it possible to pass data as initializer_list to std::array of structures?是否可以将数据作为 initializer_list 传递给 std::array 结构?
【发布时间】:2012-02-09 00:16:07
【问题描述】:

我有以下代码。基本上,我想使用聚合初始化语法初始化非 POD 结构的 std::array。 g++ 4.6 和 4.7(最新的每周快照)都无法编译代码。

#include <array>

struct TheClass {

    int a1, a2;

    TheClass(int b1, int b2) : a1{b1}, a2{b2} {};    
};

template<unsigned D>
struct OtherClass {

    std::array<TheClass, D> a;

    OtherClass(std::array<TheClass, 2> b) : a{b} {};
};

int main()
{
    OtherClass<2>{{ {1, 2}, {2, 3} }}; //tried a lot of options here
}

GCC 错误:

v.cpp: In function ‘int main()’:
v.cpp:20:37: error: no matching function for call to ‘OtherClass<2u>::OtherClass(<brace-enclosed initializer list>)’
v.cpp:20:37: note: candidates are:
v.cpp:15:5: note: OtherClass<D>::OtherClass(std::array<TheClass, 2ul>) [with unsigned int D = 2u]
v.cpp:15:5: note:   no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘std::array<TheClass, 2ul>’
v.cpp:11:8: note: constexpr OtherClass<2u>::OtherClass(const OtherClass<2u>&)
v.cpp:11:8: note:   no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘const OtherClass<2u>&’
v.cpp:11:8: note: constexpr OtherClass<2u>::OtherClass(OtherClass<2u>&&)
v.cpp:11:8: note:   no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘OtherClass<2u>&&’

我的问题:上面的代码正确吗?似乎 std::array 是一个聚合,构造它的数据成员应该没有问题。也许这是 GCC 中的错误?

编辑:

OtherClass&lt;2&gt;{{ TheClass{1, 2}, TheClass{2, 3} }}; 当然可以,但我不想使用它,因为我必须在很多地方构建类。 C++11 应该支持省略TheClass。另见this question。

【问题讨论】:

  • 你试过OtherClass&lt;2&gt;{{{ TheClass {1, 2}, TheClass {2, 3} }}};吗?
  • 请查看更新后的问题。当然可以,但是 C++11 应该支持省略TheClass。
  • 您的更新不包括我评论中的额外大括号。

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


【解决方案1】:

std::array 是一个聚合包含一个数组,所以你需要一对额外的大括号来从一个常规数组初始化它:

{1,2}               // TheClass
{{1,2},{2,3}}       // TheClass[2]
{{{1,2},{2,3}}}     // std::array<TheClass,2>
{{{{1,2},{2,3}}}}   // OtherClass<2>

但是,旧版本的 GCC 似乎仍然在为此苦苦挣扎:4.5.1 rejects it,而 4.6.1 接受它。

【讨论】:

  • @jons34yp:它适用于 GCC 4.6.1,但不适用于早期版本。
  • 终于,C++ 有了一点 Lisp 精神。
  • 我认为这是标准的不一致。一方面,它说:“数组是一个聚合 (8.5.1),可以使用语法 array a = { initializer-list }; 进行初始化;其中 initializer-list 是一个逗号分隔的列表最多包含 N 个类型可转换为 T 的元素。"但这里不是这样,它需要那些实际上被标准的其他部分暗示的额外大括号。
  • @Juho,标准只允许在type var = { ... } 形式的声明中省略大括号。在这种情况下,我们没有这样的声明,因此您必须指定所有大括号。此要求目前正在 wg21 核心问题中讨论。
  • @Johannes,你的意思是std::array&lt;TheClass,2&gt; m = {{1,2},{3,4}}; 应该可以工作吗?它没有,它需要更多的一对大括号,那是因为它是一个聚合初始化,其中一个数组作为成员。我想知道为什么文字类型(int 的数组)或显式构造的对象(TheClass {1,2})在没有额外大括号的情况下仍然可以工作。我认为这是因为子聚合的省略规则(§8.5.1 第 11 段,C++2011)。也就是说,除非编写了完整的大括号,否则当成员对象本身使用列表初始化而没有显式构造函数时,语法将是模棱两可的。
猜你喜欢
  • 2016-05-31
  • 2019-02-16
  • 2022-07-06
  • 1970-01-01
  • 1970-01-01
  • 2016-10-20
  • 2018-02-25
  • 1970-01-01
  • 2021-12-28
相关资源
最近更新 更多