Union 的默认构造函数被隐式删除
Union's default constructor is implicitly deleted
以下代码:
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
If a union contains a non-static data member with a non-trivial default constructor, the default constructor of the union is deleted by default unless a variant member of the union has a default member initializer .
在我的示例中,U 中有一个带有默认成员初始值设定项的替代方案,因此不应删除默认构造函数,但确实如此。我错过了什么?
这一切都有些神秘。 gcc 与 clang 的行为相同。
standard 有话要说(强调我的):
Absent default member initializers, if any non-static data member of a union has a non-trivial default constructor, copy constructor, move constructor, copy assignment operator, move assignment operator, or destructor, the corresponding member function of the union must be user-provided or it will be implicitly deleted for the union.
但我觉得这里的措辞有点模糊。我认为他们的实际意思是您必须为具有(在您的示例中)非平凡构造函数的成员提供初始化程序,如下所示:
struct non_trivially {
non_trivially() {};
};
union U {
bool dummy;
non_trivially value { }; // <-- note that I have added an initialiser
};
int main() {
U tmp;
}
然后,it compiles.
这是CWG2084。如果您提供默认成员初始值设定项,Clang 和 gcc 在删除默认构造函数方面是错误的。
采纳后加入标准的相关引用(在[class.default.ctor]):
A defaulted default constructor for class X is defined as deleted if:
- X is a union that has a variant member with a non-trivial default constructor and no variant member of X has a default member initializer,
- [...]
- X is a union and all of its variant members are of const-qualified type (or array thereof),
(仅有的两点引用联合类型,两者都不适用,所以不应该隐式删除)
解决方法是用户提供构造函数:
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;
};
以下代码:
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
If a union contains a non-static data member with a non-trivial default constructor, the default constructor of the union is deleted by default unless a variant member of the union has a default member initializer .
在我的示例中,U 中有一个带有默认成员初始值设定项的替代方案,因此不应删除默认构造函数,但确实如此。我错过了什么?
这一切都有些神秘。 gcc 与 clang 的行为相同。
standard 有话要说(强调我的):
Absent default member initializers, if any non-static data member of a union has a non-trivial default constructor, copy constructor, move constructor, copy assignment operator, move assignment operator, or destructor, the corresponding member function of the union must be user-provided or it will be implicitly deleted for the union.
但我觉得这里的措辞有点模糊。我认为他们的实际意思是您必须为具有(在您的示例中)非平凡构造函数的成员提供初始化程序,如下所示:
struct non_trivially {
non_trivially() {};
};
union U {
bool dummy;
non_trivially value { }; // <-- note that I have added an initialiser
};
int main() {
U tmp;
}
然后,it compiles.
这是CWG2084。如果您提供默认成员初始值设定项,Clang 和 gcc 在删除默认构造函数方面是错误的。
采纳后加入标准的相关引用(在[class.default.ctor]):
A defaulted default constructor for class X is defined as deleted if:
- X is a union that has a variant member with a non-trivial default constructor and no variant member of X has a default member initializer,
- [...]
- X is a union and all of its variant members are of const-qualified type (or array thereof),
(仅有的两点引用联合类型,两者都不适用,所以不应该隐式删除)
解决方法是用户提供构造函数:
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;
};