我会尝试转换以下数据结构:
template<typename ValueT, typename ChildT>
class MyUnion
{
public:
MyUnion() : mChild(NULL) {}
private:
union {
ChildT* mChild;
ValueT* mValue;
};
};
ValueT
可以是POD类型(如int
、float
等)和非平凡类型,比如Vec3
、std::string
,这也是它最初被实现为指向动态分配内存的指针的原因。然而,使用c++11,我们现在可以直接在类中存储该值。我要的结果是:
template<typename ValueT, typename ChildT>
class MyUnion
{
public:
MyUnion() : mChild(NULL) {}
private:
union {
ChildT* mChild;
ValueT mValue;
};
};
更改这个会使编译器报错,提示缺少复制构造函数,因此我想要实现它。
MyUnion(const MyUnion& other);
MyUnion& operator=(const MyUnion& other);
最好能包括移动构造函数。之前编译器会为我实现这些函数。对于POD类型,我可以使用memcpy
或类似的方法 – 现在我仍然可以采用这种方式并期望得到正确的结果吗?
memcpy
。这正是使得像std::string
这样的类“非平凡”的原因(确切地说是不可平凡地可复制)。您需要某种方式来知道联合成员当前处于活动状态,并相应地编写您的复制构造函数。或者,使用类似boost::variant
的东西。 - Igor Tandetnikmemcpy
,在这方面我给出了一个小提示,让他看一下被复制的对象(你更直接)。话虽如此,是的 -MyUnion
需要另一个成员来跟踪您对联合体的操作,例如enum class
是一种快速的方法。 - Xeren Narcyexpected<T>
实现中的操作,可以在任何可用的开源实现中找到。例如在这里:https://github.com/martinmoene/expected-lite/blob/master/include/nonstd/expected.hpp 主要的问题是,当你想让联合被占用其他类型时,你应该显式地使用放置new进行反初始化和重新初始化。你应该提供一个小型辅助类来封装它,这至少是大多数实现所做的。 - Chris BeckVec3
是平凡可复制的,那么隐式定义的复制构造函数应该可以工作。如果它不起作用,那么Vec3
(无论它是什么)实际上不是平凡可复制的,因此不能使用memcpy
正确地复制。 - Igor Tandetnik