c++ - 为什么我不能创建一个包含 vec3 对象的联合?
问题描述
我似乎无法创建一个成员是或包含一个glm::vec3
对象的联合(一个表示坐标的对象,在这种情况下包含 3 个浮点数)。 (glm::vec 的源代码)
它在以下代码中使用:
struct Event {
enum Type{
tRaw,
tAction,
tCursor,
} type;
union {
SDL_Event raw;
struct {
uint16 actionID;
bool released;
} action;
struct {
glm::vec3 prevPos;
glm::vec3 pos;
} cursor; // offending object, compiles if this is removed
} data;
};
Visual Studio 给了我以下智能感知错误。
"Error: the default constructor of "union Event::<unnamed>" cannot be referenced -- it is a deleted function"
如果删除,联合编译没有任何问题。什么可能导致这个问题,我能做些什么来解决它?
解决方案
一旦你有一个非平凡的类型union
(因此,语言强制“正确”初始化的类型,即构造函数调用),你必须显式地编写你的构造函数/析构函数:
#include <SDL/SDL.h>
#include <glm/vec3.hpp>
#include <stdint.h>
#include <new>
#include <vector>
struct Event {
enum Type{
tRaw,
tAction,
tCursor,
} type;
struct Cursor {
glm::vec3 prevPos;
glm::vec3 pos;
};
union {
SDL_Event raw;
struct {
uint16_t actionID;
bool released;
} action;
Cursor cursor;
};
Event(const SDL_Event &raw) : type(tRaw) {
new(&this->raw) SDL_Event(raw);
}
Event(uint16_t actionID, bool released) : type(tAction) {
this->action.actionID = actionID;
this->action.released = released;
}
Event(glm::vec3 prevPos, glm::vec3 pos) : type(tCursor) {
new(&this->cursor) Cursor{prevPos, pos};
}
Event(const Event &rhs) : type(rhs.type) {
switch(type) {
case tRaw: new(&this->raw) SDL_Event(raw); break;
case tAction: memcpy((void *)&action, (const void *)&rhs.action, sizeof(action)); break;
case tCursor: new(&this->cursor) Cursor(rhs.cursor);
}
}
~Event() {
if(type == tCursor) {
this->cursor.~Cursor();
}
// in all other cases, no destructor is needed
}
};
int main() {
// Construction
Event ev(1, false);
SDL_Event foo;
Event ev2(foo);
glm::vec3 pos;
Event ev3(pos, pos);
// Copy construction & destruction
std::vector<Event> events;
events.push_back(ev);
events.push_back(ev2);
events.push_back(ev3);
events.clear();
return 0;
}
一些注意事项:
- 我避开了该
data
成员,而是选择了匿名union
;这避免了很多样板,否则我必须在内部编写这些构造函数union
(因为它是被删除并且必须显式定义union
的构造函数),然后在外部添加转发器;它还极大地简化了析构函数的编写(同样,它必须写在内部union
,但union
不知道外部type
;你可以解决这个问题,但它既乏味又冗长); - 我必须明确地命名
Cursor
联合,否则在语法上不可能调用它的析构函数(除非模板技巧); - 我没有实现赋值运算符;这并不复杂,但老实说,这很乏味。您可以在我之前在评论中发布的链接中找到基本蓝图(检查是否相同
type
;如果相同,请执行常规任务;否则,销毁活动成员并放置new
到新成员上)。
话虽如此,这些东西已经在 C++17 中以更通用的方式实现了std::variant
,所以,如果你有一个足够新的编译器,你可以考虑改用它。
推荐阅读
- azure - 无法从 Azure B2C 获取刷新令牌
- java - 如何在 Spring Boot 中使用来自 Apache Kafka 的数据
- python - 在 Python 中为装饰器添加方法
- ios - 有没有办法反转 PDFView 中的颜色?
- angular - 角度 https 请求的 CORS 问题
- python - Python 3.8:使用 append() 时出现 IndexError
- apache-spark - 使用流式数据帧进行内部连接
- c++ - std::vector 不是 push_back 值到我的向量中吗?C++
- linux - 当用户未设置时,容器从哪里获得它的限制(no_file 和类似的)?
- sql - 优化 SQL INSERT 查询