std :: array <std :: vector>中的括号删除

时间:2018-11-14 17:32:57

标签: c++ c++17 list-initialization

我正在使用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进行编译时,我期望大括号省略会起作用。

为什么大括号省略在这里不适用?

2 个答案:

答案 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.overviewstd::array

  

数组是一个聚合,最多可以将其类型转换为T的N个元素进行列表初始化。

情况并非如此。