Reputation: 1501
I desperately need to find a solution for the following problem:
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;
}
}
It's frustrating that if I add tags to p1 and p2 structs, the code will compile, but the f & ff members would not be accessible:
...
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'
}
Is there any way to make this work somehow?
Upvotes: 8
Views: 12435
Reputation: 206518
Current C++ standard does not allow non-POD types inside unions. Hence you get this compiler error from gcc.
Instead of using C unions, you should use boost::variant
. Check the doccumentation here.
To add to the above:
The new C++ standard(C++0x) adds a new feature called as Unrestricted Unions, which supports storing non-POD types to a Union.
Upvotes: 7
Reputation: 3984
C++ standard 2003 doesn't allow this (from Standard 9.5):
An object of a class with a non-trivial constructor (12.1), a non-trivial copy constructor (12.8), a non-trivial destructor (12.4), or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a member of a union, nor can an array of such objects.
But C++0x allows it, however, you need to define your own constructor because default constructor will be declared as deleted if you don't define your own.
From N3291 9.5:
If any non-static data member of a union has a non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be user-provided or it will be implicitly deleted (8.4.3) for the union.
Other people has suggested Boost.Variant. For simple fix, just remove the constructor from Flag class. Though you need to initialize it manually whenever you initialize the union object, it won't be confusing because union is essentially a C feature.
Upvotes: 0
Reputation: 361352
As @Als said, union cannot define non-POD as member data, there is one alternative. You can still define a pointer to the non-POD as member data of the union.
So this is allowed:
union
{
struct
{
Flags<4096> *pf; //pointer to non-POD
}p1;
struct
{
Flags<16384> *pff; //pointer to non-POD
}p2;
}parts;
But then Boost.Variant is a better alternative.
Upvotes: 9