Chi*_*iel 62 c++ initializer-list c++14
使用C++ 14标准,std::array可以使用单个括号进行初始化(请参阅http://en.cppreference.com/w/cpp/container/array):
然而,这并没有为工作std::array的std::pair.
为什么这些工作:
std::pair<int, int> p { 1, 2 };
std::array<int, 3> a {1, 2, 3};
Run Code Online (Sandbox Code Playgroud)
但是这不工作:
std::array<std::pair<int, int>, 3> b {{1, 11}, {2, 22}, {3, 33}};
Run Code Online (Sandbox Code Playgroud)
虽然这确实有效吗?
std::array<std::pair<int, int>, 3> b {{{1, 11}, {2, 22}, {3, 33}}};
Run Code Online (Sandbox Code Playgroud)
此外,为了完成,一个好的旧数组的初始化确实适用于单个大括号
std::pair<int, int> c[3] {{1, 11}, {2, 22}, {3, 33}};
Run Code Online (Sandbox Code Playgroud)
Jod*_*cus 30
这似乎是一个解析的怀疑,有点类似于着名的 最令人烦恼的解析.我怀疑发生了什么:
如果你写
std::array<std::pair<int, int>, 3> b {{1, 11}, {2, 22}, {3, 33}};
Run Code Online (Sandbox Code Playgroud)
编译器有两种解释语法的方法:
您执行全括号初始化(意味着最外面的大括号指的是聚合初始化std::array,而第一个最内层大括号初始化其内部成员表示std::array是真正的C-Array).这将无法编译,因为std::pair<int, int>随后无法初始化1(所有大括号都已用完).clang会给出一个编译器错误,指出:
error: no viable conversion from 'int' to 'std::pair<int, int>'
std::array<std::pair<int, int>, 3> a{{1, 11}, {2, 22}, {3, 33}};
^
Run Code Online (Sandbox Code Playgroud)
另请注意,如果没有要初始化的内部成员聚合,即此问题得以解决
std::pair<int, int> b[3] = {{1, 11}, {2, 22}, {3, 33}};
Run Code Online (Sandbox Code Playgroud)
将作为聚合初始化编译得很好.
(你的意思是它.)你执行大括号删除初始化,因此最里面的大括号用于各个对的聚合初始化,而内部数组表示的大括号被省略.请注意,即使没有这种歧义,正如在rustx的答案中正确指出的那样,大括号的规则也不适用,因为std::pair没有聚合类型,所以程序仍然是不正确的.
编译器更喜欢选项1.通过提供额外的大括号,您可以执行全括号初始化并解除任何语法歧义.
rus*_*tyx 14
C++ 14 大括号省略规则仅适用于子聚合初始化.
所以例如这样的工作:
std::array<std::array<int, 3>, 3> a{1, 11, 2, 22, 3, 33};
Run Code Online (Sandbox Code Playgroud)
在这里,聚合的聚合可以在没有额外括号的情况下进行列表初始化.
但std::pair它不是聚合(它有构造函数),因此该规则不适用.
这意味着如果没有大括号省略规则,std::array本身就是一个内部有数组的聚合,需要一组额外的大括号才能进行列表初始化.请记住,类模板array实现为:
template<typename T, std::size_t N>
struct array {
T elems[N];
};
Run Code Online (Sandbox Code Playgroud)
要在没有大括号省略规则的情况下对列表进行初始化,您需要一组额外的大括号才能获得该elems成员.
如果没有双括号,那么这个陈述就是含糊不清的.请考虑以下代码:
std::array<std::pair<int, int>, 1> a = {{ {1, 2} }};
std::array<int, 2> b = { {1, 2} };
Run Code Online (Sandbox Code Playgroud)
如果没有第一个定义双括号,编译器会将{ {1,2} }作为一个标量初始化列表的array<int, 2>.您需要声明一个显式嵌套的braced-init-list,以便编译器识别内部列表也是聚合初始化的(与标量初始化相比),这样它就可以构造一个数组std::pair.
| 归档时间: |
|
| 查看次数: |
3929 次 |
| 最近记录: |