假设有一个std::array要初始化的东西.如果使用双括号可以:
std::array<int, 2> x = {{0, 1}};
std::array<int, 2> x{{0, 1}};
Run Code Online (Sandbox Code Playgroud)
在良好的旧聚合初始化中使用单个括号也是可以的,因为括号省略将处理缺少的大括号:
std::array<int, 2> x = {0, 1};
Run Code Online (Sandbox Code Playgroud)
但是,使用单个括号的列表初始化是否可以?GCC接受它,Clang拒绝它"在使用直接列表初始化时不能省略关于子对象初始化的大括号".
std::array<int, 2> x{0, 1};
Run Code Online (Sandbox Code Playgroud)
提到括号内容的标准中唯一的部分是8.5.1/12,其中说:
使用赋值表达式初始化聚合成员时,将考虑所有隐式类型转换(第4节).如果赋值表达式可以初始化成员,则初始化成员.否则,如果成员本身是子集合,则假定使用大括号,并考虑赋值表达式初始化子集合的第一个成员.
8.5.1是关于聚合初始化的,所以应该意味着Clang是正确拒绝的,对吗?没那么快.8.5.4/3说:
列表初始化对象或类型T的引用定义如下:
[...]
- 否则,如果T是聚合,则执行聚合初始化(8.5.1).
我认为这意味着与聚合初始化完全相同的规则,包括括号elision,适用,意味着GCC是正确的接受.
我承认,措辞不是特别清楚.那么,哪个编译器正确处理第三个片段呢?括号省略是否在列表初始化中发生,或者不是?
c++ language-lawyer aggregate-initialization c++11 list-initialization