As the (Working Draft of) C++ Standard says:
9.5.1 [class.union]
In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time. [...] The size of a union is sufficient to contain the largest of its non-static data members. Each non-static data member is allocated as if it were the sole member of a struct. All non-static data members of a union object have the same address.
But I don't know how to identify which is the active member of an union and I'm not used enough to dive into the standard to locate what the standard says about it, I've tried to figure how the active member is setted but I've found how it is swapped:
9.5.4 [class.union]
[ Note: In general, one must use explicit destructor calls and placement new operators to change the active member of a union. —end note ] [Example: Consider an object
u
of aunion type U
having non-static data members m of typeM
andn
of typeN
. IfM
has a non-trivial destructor andN
has a non-trivial constructor (for instance, if they declare or inherit virtual functions), the active member of u can be safely switched fromm
ton
using the destructor and placement new operator as follows:u.m.~M(); new (&u.n) N;
—end example ]
So my guess is that the active member of an union is the one first asigned, used, constructed or placement-new'ed; but this becomes kind of tricky with uniform initialization, consider the following code:
union Foo
{
struct {char a,b,c,d;};
char array[4];
int integer;
};
Foo f; // default ctor
std::cout << f.a << f.b << f.c << f.d << '
';
Which is the active member of the union on the code above? Is std::cout
reading from the active member of the union? What about the code below?
Foo f{0,1,2,3}; // uniform initialization
std::cout << f.a << f.b << f.c << f.d << '
';
With the lines above we can initialize the nested anonymous struct or either the array, if I provide only an integer I can initialize Foo::a
or Foo::array
or Foo::integer
... which one would be the active member?
Foo f{0}; // uniform initialization
std::cout << f.integer << '
';
I guess that the active member would be the aninymous struct in all of the above cases but I'm not sure.
If I want to activate one or the other union member, should I provide a constructor activating it?
union Bar
{
// #1 Activate anonymous struct
Bar(char x, char y, char z, char t) : a(x),b(y),c(z),d(t) {}
// #2 Activate array
Bar(char (&a)[4]) { std::copy(std::begin(a), std::end(a), std::begin(array)); }
// #3 Activate integer
Bar(int i) : integer(i) {}
struct {char a,b,c,d;};
char array[4];
int integer;
};
I'm almost sure that #1 and #3 will mark as active union the anonymous struct and the integer but I don't know about the #2 because in the moment we reach the body of the constructor the members are already constructed! so are we calling std::copy
over an inactive union member?
Questions:
- Which are the active union members of
Foo
if it is constructed with the following uniform initialization:Foo{};
Foo{1,2,3,4};
Foo{1};
- In the #2 constructor of
Bar
theBar::array
is the active union member? - Where in the standard can I read about which is exactly the active union member and how to set it without placement new?