Use a union in Variant for safe type punning
Create a VaraintUnion
that is an actual C++ union
to store the data
in a Variant
.
You may be asking yourself, why not just use an std::aligned_union
rather than a real union type? That was our first implementation, but
the problem is that the std::aligned_union
reference needs to be
recast to the actual type. Typically you would do that with
reinterpret_cast
. However, doing that leads to undefined behavior. The
C++ compiler assumes that 2 pointers of different types point to
different memory (even if it is clear that they are set to the same
address). That means optimizers can remove code because it "knows" that
data in one type cannot affect data in another type. To safely change
the type of an std::aligned_union
, you really have to do an
std::memcpy
. This is problematic for types that cannot be trivially
copied. Another problem is that we found that device compilers do not
optimize the memcpy as well as most CPU compilers. Likely, memcpy is
used much less frequently on GPU devices.