如何创建此已标记联合的实例?关于已删除构造函数的编译器错误
How do I create an instance of this tagged union? Compiler errors about deleted constructor
这是我标记的联合:
struct UniformVariant
{
enum class UNIFORM_TYPE {FLOAT, INT32, VEC2, VEC3, VEC4, MAT4} type;
union
{
float f;
int i;
glm::vec2 v2;
glm::vec3 v3;
glm::vec4 v4;
glm::mat4 m4;
} value;
};
如果我试着这样使用它:
void some_function()
{
UniformVariant v;
some_other_function(v);
}
我收到一个编译错误use of deleted function 'UniformVariant::UniformVariant()'
它进一步表示,它被隐含地删除了,因为默认定义格式不正确。所以我尝试在UniformVariant
中添加一个构造函数
UniformVariant() : value(0.0f), type(UNIFORM_TYPE::FLOAT) { };
但是类似的问题。我认为这与工会中包含阶级类型有关;但我想不出正确使用它的语法。
来自[class.union]中的注释:
如果有任何非静态数据成员的具有非平凡的默认构造函数(12.1)、复制构造函数(12.8)、移动构造函数(12.8),复制赋值运算符(12.8)、移动赋值运算符(1280)或析构函数(12.4)联合的成员函数必须由用户提供,否则它将被隐式删除(8.4.3)。
该并集中的一个类型有一个非平凡的默认构造函数,因此不能默认构造该并集。考虑一下这个更简单的复制:
struct X {
X() { }
};
struct Y {
union {
float f;
X x;
} value;
};
int main()
{
Y y;
}
X
有一个非平凡的默认构造函数,因此Y::Y()
被隐式删除,因为匿名联合默认构造函数被隐式地删除。
然而,您可以为该联合提供自己的默认构造函数:
union U {
U() : f(0.f) { }
float f;
X x;
} value;
现在该示例编译完毕。
然而,如果你只是在实现自己的标记联合,我强烈建议你使用Boost.Variant。它非常有用,正好解决了这个问题。
当前联合的问题是它没有指定哪个成员最初应该是活动的。
C++11确实有一个名为匿名联合的功能,在该功能中,最初没有成员处于活动状态,您可以根据需要激活每个成员。如果列表中没有具有非平凡构造函数的类型,则此功能对于实现您正在尝试的类似Variant的对象至关重要。
但是,您的联合不是匿名的,因为它有一个命名实例value
。
如果非匿名联合包含任何具有非平凡构造函数的成员(例如glm
类),则该联合必须具有一个构造函数,该构造函数仅初始化其中一个成员。(即使提供大括号或相等的初始值设定项也不够)。
除了巴里的好建议之外,你的另一个选择是改用匿名联盟:
union
{
float f;
int i;
glm::vec2 v2;
glm::vec3 v3;
glm::vec4 v4;
glm::mat4 m4;
};
// ^^^^^ no name
当这种情况发生时,f
、i
、v2
等将被"提升"为UniformVariant
级别的名称。你现在可以写:
UniformVariant v;
v.i = 1;
再次解释初始化:当结构包含匿名并集时,它实际上不会初始化任何成员。在使用成员时,必须手动构造和销毁它。
对于像int
这样的基元类型,您可以通过分配给它们来激活它们,而不需要去激活。但对于类类型,您必须使用placement-new和析构函数调用,例如:
new(&v2) glm::vec2(...args...);
当你处理完该成员时:
v2.~vec2();
为了避免错误,您可能希望使并集位于private
部分,并为X
成员提供用于设置活动成员的函数。
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 我收到以下错误:抛出'std::bad_alloc'实例后终止调用
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 为什么创建友元类的实例会导致"undefined reference to"错误?
- 错误 没有与参数列表匹配的重载函数"getline"实例
- 错误的cv::face FacemarkLBF实例化
- C++应用程序 MySQL odbc 数据库连接错误:在引发"otl_tmpl_exception<>"实例后终止调用
- 无法使用 SWIG 在 Python 中实例化C++类(获取属性错误)
- 在抛出 'std::runtime_error' 的实例后终止调用 what(): Filebuf 和 ostream 的 I/O 错误
- gcc出现不明确的模板实例化错误
- 结构数组的构造函数错误,错误消息:没有构造函数实例与参数列表匹配
- 尝试实例化模板类的对象时出现"No Matching Constructor"错误
- 返回实例变量的c++方法可以访问变量中的数据,但不能更改它,但在编译时不会生成错误
- 使用to_string、reverse、stoi组合的C++反转编号给出运行时错误实例超出范围
- 无法实例化抽象类错误
- C++ Visual Studio 重载函数错误:没有重载函数的实例与指定的类型匹配
- 错误 C2280 / 在 std::vector 中实例化对象时复制构造函数出现问题?
- 为什么自删除的全局 Vulkan 实例仅在添加层时才导致段错误?
- 类属性包括模板类的实例(错误 C3857)
- c++类实例错误lnk2019