What is the modern, correct way to do type punning in C++?

First of all, you assume that sizeof(long) == sizeof(int) == sizeof(float). This is not always true, and totally unspecified (platform dependent). Actually, this is true on my Windows using clang-cl and wrong on my Linux using the same 64-bit machine. Different compilers on the same OS/machine can give different results. A static assert is at least required to avoid sneaky bugs.

Plain C casts, reinterpret casts and static casts are invalid here because of the strict aliasing rule (to be pedantic, the program is ill-formed in this case regarding the C++ standard). The union solution is not valid too (it is only valid in C, not in C++). Only the std::bit_cast and the std::memcpy solution are “safe” (assuming the size of the types are matching on the target plateform). Using std::memcpy is often fast as it is optimized by most mainstream compiler (when optimizations are enabled, like with -O3 for GCC/Clang): the std::memcpy call can be inlined and replaced by faster instructions. std::bit_cast is the new way of doing this (only since C++20). The last solution is cleaner for a C++ code as std::memcpy use unsafe void* types and thus by-pass the type system.

Leave a Comment