为什么不能使用两层列表初始化器来初始化2D std :: array? [英] Why can't a 2D std::array be initialized with two layers of list-initializers?

查看:116
本文介绍了为什么不能使用两层列表初始化器来初始化2D std :: array?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

can someone help me understand why my compiler can't/doesn't deduce this? (using 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}};
}

奇怪的是,这也失败了:

Also weirdly this fails too:

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

@ 1201ProgramAlarm指出,添加另一组花括号是可行的:

@1201ProgramAlarm pointed out that adding another set of curly braces works:

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

它正在使用聚合初始化,因为std::array没有brace-init-list的构造函数.很好,但是为什么/如何工作?

It's using aggregate initialization, because std::array has no constructor for brace-init-list. That's fine, but then why/how does this work?

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

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

why does it handle this case but not the nested case?

推荐答案

容器std::array等效地是一个持有C数组的结构(实现可能不会以这种方式实现std::array,但它应保证语义是相同的),因此应使用两层花括号将其初始化,即

The container std::array is equivalently a struct holding a C-array (an implementation may not implement std::array in this way, but it should guarantee the semantic is the same), so it should be initialized by two layers of braces, i.e.

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

当然,可以像我们通常对2D数组所做的那样,删除初始化列表中的花括号:

Of course, braces in an initializer-list can be elided like what we usually do for a 2D array:

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

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

... but the initializer-list that begins with the elided braces before the elision should not begin with a left brace after the elision. In other words, if an initializer-list begins with a left brace, the compiler will not consider the possibility that this initializer-list has elided outermost braces.

在初始化程序{{0,0},{0,0}}中,子初始化程序{0,0},{0,0}以左花括号开头,因此可用于初始化C数组本身.但是,列表中有两个子句,而只有一个C数组,则会发生错误.

In your initializer {{0,0},{0,0}}, the sub-initializer {0,0},{0,0} begins with a left brace, so it is used to initialize the C-array itself. However, there are two clauses in the list while there is only one C-array, an error occurs.

在初始化程序{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并非以左括号开头.

In your initializer {std::array<double,2>{0,0},{0,0}}, the sub-initializer std::array<double,2>{0,0},{0,0} does not begin with a left brace, so it can be used to initialize the elements of the C-array, which is OK (recursively, {0,0} is OK to initialize an std::array<double,2> because the sub-initializer 0,0 does not begin with a left brace).

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

A suggestion: with this elision rule of braces, you can elide all inner braces, just like what we usually do for a 2D array:

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

这篇关于为什么不能使用两层列表初始化器来初始化2D std :: array?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆