INEEDANSWERS
INEEDANSWERS

Reputation: 121

How do you initialize a union member after the union itself was initialized?

If it is even possible, how do you initialize a union member after the union itself was initialized?

struct U_Keeper
{
    U_Keeper() : x();
    bool HoldingTypeU {true};
    union
    {
        X x;
        Y y;
    };
};

void doSomething(){
    U_Keeper uk;
    doSomethingWithX(uk.x);
    // set uk to Y mode and initialize uk.y
    uk.HoldingTypeU = false;
};

Let's say Y is a complicated, big type that needs to be initialized. How would you go about doing that?

The reason I'm asking: I have a union like this where "Y" would be an std::string. Of course, an std::string has an assignment operator, so its values can be set later on. But I'm not sure if an std::string needs to be initialized necessarily, aside from whether it will be assigned to later on or not. Maybe when an std::string is assigned to it builds upon the data it already had: it overrides the data that was already there, thus already needing a valid pointer to the data.

Upvotes: 0

Views: 411

Answers (1)

eerorika
eerorika

Reputation: 238311

If the union members are trivial, the traditional way to activate a member is to assign it:

uk.y = some_value;

If the members are non-trivial (such as std::string), then you must instead first destroy the currently active member, and then initialise the other using placement-new:

uk.x.~X();
::new (&uk.y) Y /*parenthesised or braced init arguments here*/;

Note that if the union contains non-trivial members, then all of its special member functions - except default constructor - from destructor to copy constructor to assignment operators will be be implicitly deleted. So, you'll need to define those for the union-like class wrapping it. Each of those must know the currently active member, and act accordingly.

Note also that the destructor doesn't implicitly destroy the union member unlike normal class which would destroy members after destructor body. That must be done explicitly like I showed above.


P.S. There is a standard tagged union in the standard library: std::variant. No need to invent your own.

Upvotes: 2

Related Questions