我正在使用g++
进行C ++ 17编译。我有以下内容:
std::array<std::vector<int>, 2> v = {{ {1,2}, {3,4} }};
我不明白为什么如果我删除该数组的双括号不再起作用。
std::array<std::vector<int>, 2> v = { {1,2}, {3,4} }; // Does not compile
我了解std::array
的工作原理以及对大括号的一般要求,但是当我为C ++ 17进行编译时,我期望大括号省略会起作用。
为什么大括号省略在这里不适用?
答案 0 :(得分:7)
std::array<std::vector<int>, 2>
有效
struct array {
std::vector<int> elems[2];
};
elems
是很好的子集合。问题是,根据语言规则,如果初始化程序以{
开头,则始终假定您没有使用括号;相反,将{1, 2}
用作整个子聚合elems
的初始化程序,尝试使用1
初始化其第一个元素,并使用2
初始化第二个元素(这显然是无效的-您不能将整数转换为vector
-但不会影响解释),并且{3, 4}
被认为是elems
之后的事物的初始化程序-并且因为没有这样的事物,这是另一个错误。
使用不是 braced-init-list 的东西初始化第一个元素就足以触发括号删除:
std::array<std::vector<int>, 2> v = { std::vector<int>{1,2}, {3,4} };
请注意,从规范角度来看,该库不保证可以从其他std::array<T, N>
之外的其他任何内容或类型最多可转换为{{1的N个元素的列表中进行初始化}}”。特别是,这会排除 braced-init-list ,因为它们没有类型,并且实际上也不允许使用“双括号”,因为这只是具有单个元素的特殊情况,该元素是 braced-init -list 。
这是我们最好用代码指定的区域。核心语言规则无视简单的文字说明,实现细节将泄漏出去-并且已经这样做。
答案 1 :(得分:4)
作为T.C.指出我的原始解释不是正确的,允许大括号省略请参见[dcl.init.aggr]p15:
可以将括号括在初始化列表中,如下所示。如果 初始化列表以左大括号开头,然后是后续大括号 逗号分隔的初始化子句列表初始化元素 子集合;有更多的东西是错误的 初始化子句比元素。但是,如果是初始化列表 因为一个子集合不是以左大括号开头的,仅够了 列表中的初始化子句用于初始化元素 属于子集合;剩下的所有初始化子句都留给 初始化当前集合的下一个元素 子集合是元素。 ...
但根据array.overview,std::array
:
数组是一个聚合,最多可以将其类型转换为T的N个元素进行列表初始化。
情况并非如此。