… with constructor not allowed in union problem

你。 提交于 2019-12-23 08:18:32

问题


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?


回答1:


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.




回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/6014717/with-constructor-not-allowed-in-union-problem

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!