Search code examples
c++constructorunionsdefault-constructor

Do you always have to declare a default constructor and destructor for unions containing members with user-defined default constructor?


This class containing a union:

struct foo
{
    union
    {
        std::vector<int> vec;
        int i;
    };
};

cannot be instantiated. If I try, the compiler throws an error saying 'foo::foo(void)': attempting to reference a deleted function. To get it to work, I have to add an empty constructor and destructor to the union like so:

struct foo
{
    union U
    {
        U() {}
        ~U() {}
        std::vector<int> vec;
        int i;
    } u_;
};

It can then be instantiated successfully. Is this always the case? Why? It seems silly to write an empty constructor and destructor for every union that contains member with user-defined default constructors.


Solution

  • It seems silly to write an empty constructor and destructor for ...

    Not only silly, but actually wrong.

    Why [does the compiler doesn't generate one and you need to]?

    A union doesn't know which of its members is active. As such if at least one of its members has a non-trivial special method the union can't generate that special method because it doesn't know on which member to call that special method.

    And now we come to your case. You do need to write a special method, but having it empty achieves nothing. You need to write a special method that correctly delegates to the active member. For instance inside foo you can have a data member (an enum or an index) which tells you which union member is active. And in your union special method you check that index and call the special method on the active member of the union.

    Or you can forget about all this and just use the type in the standard library that not only has everything set up for you, but also is type safe: std::variant.