此代码在GCC 11和Clang 13(在C++20模式下(中编译时没有警告
struct A {
int x, y;
};
struct B : A { };
int main () {
A a{1,2};
B b{3,4}; // Clang 12 wants B b{{3,4}}
return a.x * b.x + a.y * b.y;
}
但在Clang 12我们有
<source>:10:9: warning: suggest braces around initialization of subobject [-Wmissing-braces]
B b{3,4};
https://godbolt.org/z/Kdnon9575
可能与有关
为什么Clang 12拒绝以C++20的方式初始化聚合?
和这些文件
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0960r3.html
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1975r0.html
在C++20下,是否正式支持单括号(没有警告(初始化这些简单的POD派生类?如果是这样的话,标准在哪里说,这样我们就可以依赖它了?
在C++17中,为了避免警告,需要使用双大括号,是吗?
在C++14中,单大括号是一个硬错误,因为派生结构不是聚合,是吗?
C++17以及C++20,https://timsong-cpp.github.io/cppwp/n4659/dcl.init.aggr#12和https://timsong-cpp.github.io/cppwp/n4868/dcl.init.aggr#15,分别允许省略括号以初始化聚合:
大括号可以在初始值设定项列表中省略,如下所示。如果初始值设定项列表以左大括号开头,则后续的逗号分隔的初始值设定项列表将初始化子聚合的成员;初始值设定项子句多于成员是错误的。但是,如果子聚合的初始值设定项列表不是以左大括号开头,则只使用列表中足够的初始值设置项子句来初始化子聚合的成员;剩下的任何初始值设定项子句都将初始化当前子聚合所属聚合的下一个成员。
OP示例中的B类是C++17和C++20中的一个聚合(根据C++17的P0017R1及其主要对[dcl.init.agr]/1的更新(,其中对聚合的要求相对于基类要求更加宽松。
聚合是一个数组或具有的类([class](
- […]
- (C++14(没有基类
- (C++17和C++20(没有虚拟、私有或受保护的基类
现在,Clang诊断一开始只是一个警告,截至Clang 13,它似乎已经(imo正确地(被删除,用于具有基类的聚合的支持-消除初始化。警告可能是C++14中的一个剩余角情况,其中B不是聚合,但由于初始化形式无效,程序将不正确。