为什么 "missing double brace warning" 用于 Clang 12 中的 BaseClass 聚合初始化而不是 Clang 13 或 GCC 11?

why "missing double brace warning" for BaseClass Aggregate initialisation in Clang 12 but not Clang 13 or GCC 11?

此代码在 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

可能与:

有关

和这些论文

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 Derived 类?如果是这样,标准在哪里说的,所以我们可以依靠它?

在 C++17 中,双括号是必需的,以避免警告,是吗?

在 C++14 中,单大括号是一个硬错误,因为派生结构不是聚合,是吗?

C++17 和 C++20,https://timsong-cpp.github.io/cppwp/n4659/dcl.init.aggr#12 and 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.

Class OP 示例中的 B 是 C++17 和 C++20 中的聚合(根据 C++17 的 P0017R1 and its updates primarily to [dcl.init.aggr]/1),其中符合条件的要求对于基本 class 要求,聚合已变得更加宽松。

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 开始,它似乎已经(我认为是正确的)已被删除,用于对具有基数 classes 的聚合进行大括号省略初始化.警告可能是 C++14 中的残余极端情况,其中 B 不是聚合,但由于初始化形式无效,程序格式错误。