此代碼在 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 中,單括號是一個硬錯誤,因為派生結構不是聚合,是嗎?
uj5u.com熱心網友回復:
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.aggr]/1 的更新),其中符合條件的要求作為一個聚合,在基類要求方面已經變得更加寬松。
聚合是一個陣列或一個類 ([class])
- [...]
- (C 14) 沒有基類
- (C 17 和 C 20)沒有虛擬、私有或受保護的基類
現在,Clang 診斷一開始只是一個警告,從 Clang 13 開始,它似乎已經(imo 正確)被洗掉,用于對具有基類的聚合進行括號省略初始化。警告可能是 C 14 中的一個殘余極端情況,其中 B 不是聚合,但由于初始化形式無效,程式格式錯誤。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/409055.html
標籤:
