In some performance-oriented algorithms, a solution to certain slow operations is reinterpreting a value as a different type of the same length
while preserving its binary representation.
One of the superseded solutions, known as "union type-punning", is to use a union
with two members with types corresponding to the
source and the target types of the cast. The operation is performed by saving the value in the member of the source type and then reading the value
from the member of the target type. Despite being allowed in C, this operation has undefined behavior according to C++ standard and should be replaced
by std::memcpy
(or std::bit_cast
in C++20).
Note: std::memcpy
has no performance impact on modern compilers when used in type-punning and is optimized during compilation.
Sometimes union
type-punning is used to remove const
. This can create readability issues and should be replaced with
const_cast
.
This rule raises an issue on any use of a union
that should be replaced with std::memcpy
, std::bit_cast
, or
const_cast
.
What is the potential impact?
The C++ standard states that only one union
member can be "active" at any time. A member becomes active once assigned a value, making
the other union
members "inactive". The standard also states that reading from an "inactive" member is undefined behavior.
Since union
type-punning relies on reading the "inactive" member, code using it exercises undefined behavior. Such code can be
unintentionally removed in aggressive levels of optimization.
Further problems could also arise from using union
-based type punning in cross-platform solutions. Since this method is mainly used
with Built-in Types, which vary in size depending on the underlying architecture, it could hide a portability issue.