此代码在 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
可能与:
Why does Clang 12 refuse to initialize aggregates in the C++20 way?
和这些论文
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 ,分别允许聚合初始化的大括号省略:
Braces can be elided in an initializer-list as follows. If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the members of a subaggregate; it is erroneous for there to be more initializer-clauses than members. If, however, the initializer-list for a subaggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the members of the subaggregate; any remaining initializer-clauses are left to initialize the next member of the aggregate of which the current subaggregate is a member.
OP 示例中的 B 类是 C++17 和 C++20 中的聚合(根据 C++17 的 P0017R1 及其主要对 [dcl.init.aggr]/1 的更新),其中符合条件的要求聚合在基类要求方面变得更加宽松。
An aggregate is an array or a class ([class]) with
- [...]
- (C++14) no base classes
- (C++17 and C++20) no virtual, private, or protected base classes
现在,Clang 诊断只是一开始的警告,从 Clang 13 开始,它似乎(我认为是正确的)已被删除,以用于具有基类的聚合的大括号省略初始化。警告可能是来自 C++14 的残余极端情况,其中 B 不是聚合,但程序由于无效的初始化形式而格式错误。
关于c++ - 为什么 "missing double brace warning"用于 Clang 12 中的 BaseClass 聚合初始化而不是 Clang 13 或 GCC 11?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70672136/