【问题标题】:Why can't a 2D std::array be initialized with two layers of list-initializers?为什么不能用两层列表初始化器初始化 2D std::array?
【发布时间】:2018-09-08 02:49:17
【问题描述】:

有人能帮我理解为什么我的编译器不能/不能推断出这个吗? (使用 g++ 7.3)

不起作用:

#include <array>
std::array<std::array<double,2>,2> f() {
 return {{0,0},{0,0}};
}

工作正常:

#include <array>
std::array<std::array<double,2>,2> f() {
 return {std::array<double,2>{0,0},{0,0}};
}

奇怪的是,这也失败了:

#include <array>
std::array<std::array<double,2>,2> f() {
 return std::array<std::array<double,2>,2>{{0,0},{0,0}};
}

@1201ProgramAlarm 指出添加另一组花括号有效:

#include <array>
std::array<std::array<double,2>,2> f() {
 return {{{0,0},{0,0}}};
}

它使用聚合初始化,因为std::array 没有用于大括号初始化列表的构造函数。这很好,但是为什么/如何工作呢?

std::array<double,2> x{1,2};

为什么它处理这种情况而不是嵌套情况?

【问题讨论】:

标签: c++ stdarray list-initialization


【解决方案1】:

容器std::array等价于一个struct保存一个C-array(一个实现可能不会以这种方式实现std::array,但它应该保证语义相同),所以它应该由两层初始化大括号,即

#include <array>
std::array<std::array<double,2>,2> f() {
   return {{{{0,0}},{{0,0}}}};
} 

当然,初始化列表中的大括号可以像我们通常对二维数组所做的那样被省略:

int arr[2][2] = {0,1,2,3};

...但是以省略号之前的大括号开头的初始化列表不应以省略号之后的左大括号开头。换句话说,如果初始化列表以左大括号开头,编译器将不会考虑此初始化列表已省略最外层大括号的可能性。

在您的初始化程序{{0,0},{0,0}} 中,子初始化程序{0,0},{0,0} 以左大括号开头,因此它用于初始化C 数组本身。但是,列表中有两个子句,而只有一个 C 数组,就会出错。

在你的初始化器{std::array&lt;double,2&gt;{0,0},{0,0}}中,子初始化器std::array&lt;double,2&gt;{0,0},{0,0}不以左大括号开头,所以它可以用来初始化C数组的元素,这样就OK了(递归,{0,0}是可以初始化 std::array&lt;double,2&gt;,因为子初始化器 0,0 不以左大括号开头)。


一个建议:使用大括号的省略规则,您可以省略所有内大括号,就像我们通常对二维数组所做的那样:

#include <array>
std::array<std::array<double,2>,2> f() {
   return {0,0,0,0};
} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-17
    • 2021-03-19
    • 2015-10-05
    • 2012-02-10
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多