Введите штамповку с шаблонами

Я хотел бы знать, является ли следующий код приемлемым методом для обработки типов, таким образом, чтобы не нарушать строгие правила псевдонимов. Я понимаю, что этот метод основан на расширении компилятора GCC, поэтому нет необходимости указывать на это.

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);
}

Пример использования:

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);

4

Решение

Я склонен использовать союз для этого. Что-то вроде:

template <class output_type, class input_type>
inline output_type punning_cast(const input_type& input)
{
union {
input_type in;
output_type out;
} u;

u.in = input;
return u.out;
}

Строго говоря, это Неопределенное поведение в C ++ (хотя не в С). Но то же самое относится и к вам, и мне еще предстоит увидеть компилятор C ++, который не «делает то, что я хочу» для этой конструкции … Так что я считаю, что это довольно переносимый способ сделать наложение типов.

Лучшая альтернатива, я думаю, это просто использовать memcpyи это, вероятно, то, что я бы сделал для версии вашего кода с «указателем». Хороший компилятор встроит вызов, поэтому не должно быть никакого снижения производительности.

Я нахожу union формулировку легче читать.

[Обновить]

Документация GCC говорит:

Практика чтения от другого члена профсоюза, чем тот,
последнее, что написано (называется «типовое наказание»), является обычным явлением. Даже с
-fstrict-aliasingдопускается типирование, если доступ к памяти осуществляется через тип объединения.

Так что GCC, по крайней мере, специально поддерживает использование объединения.

5

Другие решения


По вопросам рекламы [email protected]