假设有一个std::array
要初始化的。如果使用双括号也没关系:
std::array<int, 2> x = {{0, 1}};
std::array<int, 2> x{{0, 1}};
在旧的聚合初始化中使用单大括号也是可以的,因为大括号省略会处理丢失的大括号:
std::array<int, 2> x = {0, 1};
但是,可以使用带有单括号的列表初始化吗?GCC 接受它,Clang 以“使用直接列表初始化时不能省略子对象初始化周围的大括号”来拒绝它。
std::array<int, 2> x{0, 1};
标准中唯一提到大括号省略的部分是 8.5.1/12,它说:
当使用赋值表达式初始化聚合成员时,会考虑所有隐式类型转换(第 4 条)。如果赋值表达式可以初始化成员,则初始化该成员。否则,如果成员本身是子聚合,则假定大括号省略,并考虑使用赋值表达式来初始化子聚合的第一个成员。
8.5.1 具体是关于聚合初始化,所以这应该意味着 Clang 拒绝是正确的,对吧?没那么快。8.5.4/3 说:
类型 T 的对象或引用的列表初始化定义如下:
[…]
— 否则,如果 T 是一个聚合,则执行聚合初始化 (8.5.1)。
我认为这意味着与聚合初始化完全相同的规则,包括大括号省略、应用,这意味着 GCC 可以正确接受。
我承认,措辞不是特别清楚。那么,哪个编译器在处理第三个片段时是正确的?大括号省略是否发生在列表初始化中,还是没有?