为什么不能用两层列表初始值设定项初始化 2D std::array?

Why can't a 2D std::array be initialized with two layers of list-initializers?

本文关键字:初始化 std array 2D 不能 列表 两层 为什么      更新时间:2023-10-16

有人可以帮助我理解为什么我的编译器不能/不推断出这一点吗?(使用 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};

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

容器std::array等效地是一个保存 C 数组的结构(实现可能不会以这种方式实现std::array,但它应该保证语义是相同的(,所以它应该由两层大括号初始化,即

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

当然,初始值设定项列表中的大括号可以省略,就像我们通常对 2D 数组所做的那样:

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

。但是,在省略号之前以省略大括号开头的初始值设定项列表不应以省略号之后的左大括号开头。换句话说,如果初始值设定项列表以左大括号开头,则编译器不会考虑此初始值设定项列表省略了最外大括号的可能性。

在初始值设定项{{0,0},{0,0}}中,子初始值设定项{0,0},{0,0}以左大括号开头,因此它用于初始化 C 数组本身。但是,列表中有两个子句,而只有一个 C 数组,则会发生错误。

在初始值设定项{std::array<double,2>{0,0},{0,0}}中,子初始值设定项std::array<double,2>{0,0},{0,0}不以左大括号开头,因此可用于初始化 C 数组的元素,这是可以的(递归地,{0,0}可以初始化std::array<double,2>,因为子初始值设定项0,0不以左大括号开头(。


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

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