简体   繁体   English

std :: array中的brace elision <std::vector>

[英]Brace elision in std::array<std::vector>

I'm compiling using g++ for C++ 17. I have the following: 我正在使用g++编译C ++ 17.我有以下内容:

std::array<std::vector<int>, 2> v = {{ {1,2}, {3,4} }};

I don't understand why if I remove the double braces for the array it does not work anymore. 我不明白为什么如果我删除数组的双括号它不再工作。

std::array<std::vector<int>, 2> v = { {1,2}, {3,4} }; // Does not compile

I understand how std::array works and the need for the double braces in general, but as I'm compiling for C++17 I expected brace elision to come into play. 我理解std::array是如何工作的以及一般双括号的需要,但是当我为C ++ 17编译时,我预计大括号将会发挥作用。

Why is brace elision not applicable here? 为什么括号不适用于此?

std::array<std::vector<int>, 2> is effectively std::array<std::vector<int>, 2>是有效的

struct array {
    std::vector<int> elems[2];
};

elems is a subaggregate just fine. elems是一个小分类就好了。 The issue is that per the language rules, if the initializer starts with a { it's always assumed that you aren't eliding braces; 问题在于,根据语言规则,如果初始化程序以{始终假设您没有删除括号; instead, {1, 2} is taken as the initializer of the entire subaggregate elems , attempting to initialize its first element with 1 and second element with 2 (this is obviously invalid - you can't convert an integer to a vector - but doesn't affect the interpretation), and {3, 4} is considered the initializer for the thing after elems - and since there are no such thing, it's another error. 相反, {1, 2}被作为整个子聚集的初始化elems ,试图与初始化其第一元件1和第二元件与2 (这显然是无效-你不能转换为一个整数vector -但没有按“T影响解释)和{3, 4}被认为是用于初始化后的事情elems -而且,因为没有这样的东西,它的另一个错误。

Initializing the first element with something that's not a braced-init-list is sufficient to trigger brace elision: 使用不是braced-init-list的东西初始化第一个元素足以触发大括号省略:

std::array<std::vector<int>, 2> v = { std::vector<int>{1,2}, {3,4} }; 

Note that from a specification perspective, the library doesn't guarantee initialization of std::array<T, N> from anything other than another std::array<T, N> or a list of "up to N elements whose types are convertible to T ". 注意,从一个规范的角度来看,库不保证初始化std::array<T, N>从比另一个的任何其他std::array<T, N>或列表“多达N个元件,其类型为可转换为T “。 This notably excludes braced-init-list s because they have no type, and actually also disallows "double braces" because that's just a special case of having a single element that is a braced-init-list . 这显然不包括braced-init-list,因为它们没有类型,实际上也不允许“双括号”,因为这只是一个特殊情况,它有一个单独的元素是一个braced-init-list

This is an area where we may have been better off specifying it with code. 这是一个我们可能最好用代码指定它的区域。 The core language rules defy easy specification in words and the implementation details will leak out - and have already done so. 核心语言规则无法用语言轻松规范,实现细节也会漏掉 - 而且已经这样做了。

As TC pointed out my original interpretation was not corret, brace elision is allowed see [dcl.init.aggr]p15 : 正如TC指出我的原始解释不正确,允许括号省略[dcl.init.aggr] p15

Braces can be elided in an initializer-list as follows. 可以在初始化列表中省略大括号,如下所示。 If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the elements of a subaggregate; 如果初始化列表以左括号开头,则后续的逗号分隔的initializer-clause列表初始化子集合的元素; it is erroneous for there to be more initializer-clauses than elements. 因为有更多的初始化子句而不是元素是错误的。 If, however, the initializer-list for a subaggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the elements of the subaggregate; 但是,如果subaggregate的初始化列表不以左括号开头,则只从列表中获取足够的initializer-clause来初始化subaggregate的元素; any remaining initializer-clauses are left to initialize the next element of the aggregate of which the current subaggregate is an element. 剩下的任何初始化子句都用于初始化当前子聚合为元素的聚合的下一个元素。 ... ...

but std::array according to array.overview : 但是根据array.overview的 std::array

An array is an aggregate that can be list-initialized with up to N elements whose types are convertible to T. 数组是一个聚合,可以使用最多N个元素进行列表初始化,这些元素的类型可以转换为T.

which is not the case we have. 这不是我们的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM