Unions are very useful tools, but come with a few important caveats:
It is undefined behavior, per the C++ standard, to access an element of a union that was not the most recently modified member. Although a lot of C++ compilers permit this access in well defined ways, these are extensions and cannot be guaranteed across compilers.
std::variant (since C++17) is like a union, only it tells you what it currently contains (part of its visible state is the type of the value it holds at a
given moment: it enforces value access happening only to that type).
Implementations do not necessarily align members of different sizes to the same address.