Is the following code legal (in c++11/14)?
bool foo() {
union bar { int i; bool b; };
union baz { char c; bar b; };
auto b = baz{'x'};
auto barptr = &b.b;
auto boolptr = &barptr->b;
new (boolptr) bool{true};
return b.b.b;
}
This example is silly, but I'm playing around with a variadic variant
implementation that uses nested unions instead of a char []
block for the variant members, and allowing this will make my current attempt at the copy constructor cleaner.
To break it down into two subquestions:
boolptr
by accessing a member of barptr
legal even though b.b
is inactive?boolptr
activate b.b
and b.b.b
?References to the standard would be appreciated.
union { member_list }; Its members can be accessed directly in the scope where this union is declared, without using the x.y or p->y syntax. Anonymous unions can be global, nested, or unnested.
A union cannot have base classes and cannot be used as a base class. A union cannot have non-static data members of reference types. Unions cannot contain a non-static data member with a non-trivial special member function (copy constructor, copy-assignment operator, or destructor).
You can declare a structure or union type separately from the definition of variables of that type, as described in Structure and union type definition and Structure and union variable declarations; or you can define a structure or union data type and all variables that have that type in one statement, as described in ...
Access members of a union We use the . operator to access members of a union. And to access pointer variables, we use the -> operator.
As with so many questions about unions and type-punning, it's unclear if your program has defined behavior although I strongly expect it to behave as expected in any sane implementation. What I can say with certitude is that this program:
#include <memory>
#include <new>
template <typename T>
inline void destruct(T& t) { t.~T(); }
template <typename T, typename...Args>
inline void construct(T& t, Args&&...args) {
::new((void*)std::addressof(t)) T(std::forward<Args>(args)...);
}
template <typename T>
inline void default_construct(T& t) {
::new((void*)std::addressof(t)) T;
}
bool foo() {
union bar { int i; bool b; };
union baz { char c; bar b; };
auto b = baz{'x'};
destruct(b.c);
default_construct(b.b);
construct(b.b.b, true);
return b.b.b;
}
is standard-compliant, has exactly the effects you desire, and compiles to exactly the same assembly as the original program in modern compilers. Original:
foo():
movl $1, %eax
ret
Guaranteed-compliant:
foo():
movl $1, %eax
ret
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With