以下代碼:
struct non_trivially {
non_trivially() {};
};
union U {
bool dummy{false};
non_trivially value;
};
int main() {
U tmp;
}
https://godbolt.org/z/1cMsqq9ee
在 clang (13.0.0) 上產生下一個編譯器錯誤:
source>:11:7: error: call to implicitly-deleted default constructor of 'U'
U tmp;
^ <source>:7:19: note: default constructor of 'U' is implicitly deleted because variant field 'value' has a non-trivial default constructor
non_trivially value;
但使用 MSVC (19.30) 成功編譯。
根據 cppreference 它應該是一個有效的代碼:https : //en.cppreference.com/w/cpp/language/union
如果聯合包含具有非平凡默認建構式的非靜態資料成員,則默認情況下洗掉聯合的默認建構式,除非聯合的變體成員具有默認成員初始值設定項。
在我的示例中, U 中有一個帶有默認成員初始值設定項的替代方法,因此不應洗掉默認建構式,但確實如此。我錯過了什么?
uj5u.com熱心網友回復:
這是CWG2084。如果您提供默認成員初始值設定項,Clang 和 gcc 洗掉默認建構式是錯誤的。
通過更改后添加到標準中的相關參考(在 [class.default.ctor] 中):
在以下情況下,類 X 的默認默認建構式被定義為已洗掉:
- X 是一個聯合,它有一個帶有非平凡默認建構式的變體成員,并且 X 的變體成員沒有一個默認成員初始值設定項,
- [...]
- X 是一個聯合并且它的所有變體成員都是 const 限定型別(或其陣列),
(作為唯一兩個參考聯合型別的點,沒有一個適用,因此不應隱式洗掉)
解決方法是用戶提供一個建構式:
union U {
constexpr U() : dummy{false} {}
bool dummy;
non_trivially value;
};
// Or this also seems to work
union U {
constexpr U() {}
bool dummy{false};
non_trivially value;
};
uj5u.com熱心網友回復:
這一切都有些神秘。 gcc 的行為與 clang 相同。
該標準有這樣的說法(強調我的):
缺少默認成員初始值設定項,如果聯合的任何非靜態資料成員具有非平凡的默認建構式、復制建構式、移動建構式、復制賦值運算子、移動賦值運算子或解構式,則聯合的相應成員函式必須是 user -provided 否則它將為聯合隱式洗掉。
但我認為這里的措辭有點毛茸茸的。我認為它們的實際意思是您必須為具有(在您的示例中)一個非平凡建構式的成員提供一個初始化程式,如下所示:
struct non_trivially {
non_trivially() {};
};
union U {
bool dummy;
non_trivially value { }; // <-- note that I have added an initialiser
};
int main() {
U tmp;
}
然后,它編譯.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/387770.html
下一篇:實作WASM文本格式的結構體
