I would like to know if the following code is an acceptable method to handle type punning in a way that doesn't break strict aliasing rules. I realize that this method relies on a GCC compiler extension, so there is no need to point that out.
template <class output_type, class input_type>
inline output_type punning_cast(const input_type& input)
{
static_assert(std::is_pod<output_type>::value, "output_type for punning_cast must be POD");
static_assert(std::is_pod<input_type>::value, "input_type for punning_cast must be POD");
static_assert(sizeof(output_type) == sizeof(input_type), "input_type and output_type must be the same size");
typedef output_type __attribute__((may_alias)) output_type_may_alias;
return *reinterpret_cast<const output_type_may_alias*>(&input);
}
template <class output_type, class input_type>
inline output_type punning_cast(const input_type* input)
{
static_assert(std::is_pod<output_type>::value, "output_type for punning_cast must be POD");
static_assert(std::is_pod<input_type>::value, "input_type for punning_cast must be POD");
typedef output_type __attribute__((may_alias)) output_type_may_alias;
return *reinterpret_cast<const output_type_may_alias*>(input);
}
Example usage:
uint32_t float_as_int = punning_cast<uint32_t>(3.14f);
unsigned char data[4] = { 0xEF, 0xBE, 0xAD, 0xDE };
uint32_t magic = punning_cast<uint32_t>(data);