Search code examples
c++inheritanceunionsdiamond-problem

C++ - union with nontrivial class member type?


I'm working with a union which has a member that is a class that uses diamond inheritance, but the program encounters a segmentation fault upon assignment to this member.

My suspicion is that I need to add some copy constructors, but after multiple attempts, the correct way to do this still evades me.

I've included a minimal, reproducible example here.

struct Base
{
    Base() : a(0) {}
    Base(int x) : a(x) {}

    int a;
};

struct Derived1 : virtual public Base
{
    Derived1() {}
};

struct Derived2 : virtual public Base
{
    Derived2() {}
};

struct Final : public Derived1, public Derived2
{
    Final() {}
};

union Example
{
    Final value;
    int i;
};

int main()
{
    Example example{ Final() };
    example.i = -1;

    /* Segfault on the line below. 
     * If the above line

       example.i = -1;
     
     * is removed, the segfault is not encountered. */

    example.value = Final();
}

My thanks to anyone who knows how to do this.


Solution

  • Since the Base class is virtual, most likely there are some internal control structures, which become destroyed, when you assign

    example.i = -1;
    

    When you recreate value, e.g.

    new(&example.value) Final();
    example.value = Final();
    

    before the assignment, the segmentation fault goes away. Although, I wouldn't recommend this hack.


    As already mentioned in the comments, a std::variant would be more appropriate, if you have C++17 available. The example would then become

    std::variant<Final, int> example{ Final() };
    example = -1;
    example = Final();