我迫切需要找到解决以下问题的方法:
namespace test
{
template <int param = 0> struct Flags
{
int _flags;
Flags()
{
_flags = 0;
}
Flags(int flags)
{
_flags = flags;
}
void init()
{
}
};
union example
{
struct
{
union
{
struct
{
Flags<4096> f;
}p1; //error: member 'test::example::<anonymous struct>::<anonymous union>::<anonymous struct> test::example::<anonymous struct>::<anonymous union>::p1' with constructor not allowed in union
struct
{
Flags<16384> ff;
}p2; //error: member 'test::example::<anonymous struct>::<anonymous union>::<anonymous struct> test::example::<anonymous struct>::<anonymous union>::p2' with constructor not allowed in union
}parts;
byte bytes[8];
}data;
int data1;
int data2;
}
}
令人沮丧的是,如果我将标签添加到p1和p2结构,代码将编译,但f&amp; ff成员无法访问:
...
struct p1
{
Flags<4096> f;
};
struct p2
{
Flags<4096> ff;
};
...
void test()
{
example ex;
ex.data.bytes[0] = 0; //Ok
ex.data.parts.p1.f.init(); //error: invalid use of 'struct test::example::<anonymous struct>::<anonymous union>::p1'
}
有什么方法可以以某种方式完成这项工作吗?
答案 0 :(得分:9)
所以这是允许的:
union
{
struct
{
Flags<4096> *pf; //pointer to non-POD
}p1;
struct
{
Flags<16384> *pff; //pointer to non-POD
}p2;
}parts;
但是Boost.Variant是一个更好的选择。
答案 1 :(得分:7)
当前的C ++标准不允许联盟内的非POD类型。因此,您从gcc中获得此编译器错误
您应该使用boost::variant
而不是使用C联合。检查doccmentation here。
添加到上述内容:
新的C ++标准(C ++ 0x)添加了一个名为 Unrestricted Unions 的新功能,它支持将非POD类型存储到联盟。
答案 2 :(得分:0)
C ++标准2003不允许这样做(来自标准9.5):
带有a的类的对象 非平凡的构造函数(12.1),a 非平凡的拷贝构造函数(12.8),a 非平凡的析构函数(12.4),或者 非平凡的复制赋值运算符 (13.5.3,12.8)不能成为a的成员 联盟,也不可能有这样的一系列 对象。
但是C ++ 0x允许它,但是,你需要定义自己的构造函数,因为如果没有定义自己的构造函数,默认构造函数将被声明为已删除。
来自N3291 9.5:
如果有任何非静态数据成员 工会有一个非平凡的违约 构造函数(12.1),复制构造函数 (12.8),移动构造函数(12.8),复制 赋值运算符(12.8),移动 赋值运算符(12.8),或 析构函数(12.4),对应的 联盟的成员函数必须是 用户提供的或隐含的 已删除(8.4.3)联盟。
其他人建议使用Boost.Variant。对于简单的修复,只需从Flag类中删除构造函数。虽然您需要在初始化union对象时手动初始化它,但它不会令人困惑,因为union本质上是一个C功能。