Graças ao comentário de Lincoln abaixo, alterei esta resposta.
A resposta a seguir lida corretamente com entradas de 8 bits em tempo de compilação. No entanto, eles exigem C ++ 17. Se você não possui C ++ 17, precisará fazer outra coisa (por exemplo, fornecer sobrecargas dessa função, uma para uint8_t e outra para int8_t, ou usar algo além de "if constexpr", talvez enable_if).
template< typename T >
std::string int_to_hex( T i )
{
// Ensure this function is called with a template parameter that makes sense. Note: static_assert is only available in C++11 and higher.
static_assert(std::is_integral<T>::value, "Template argument 'T' must be a fundamental integer type (e.g. int, short, etc..).");
std::stringstream stream;
stream << "0x" << std::setfill ('0') << std::setw(sizeof(T)*2) << std::hex;
// If T is an 8-bit integer type (e.g. uint8_t or int8_t) it will be
// treated as an ASCII code, giving the wrong result. So we use C++17's
// "if constexpr" to have the compiler decides at compile-time if it's
// converting an 8-bit int or not.
if constexpr (std::is_same_v<std::uint8_t, T>)
{
// Unsigned 8-bit unsigned int type. Cast to int (thanks Lincoln) to
// avoid ASCII code interpretation of the int. The number of hex digits
// in the returned string will still be two, which is correct for 8 bits,
// because of the 'sizeof(T)' above.
stream << static_cast<int>(i);
}
else if (std::is_same_v<std::int8_t, T>)
{
// For 8-bit signed int, same as above, except we must first cast to unsigned
// int, because values above 127d (0x7f) in the int will cause further issues.
// if we cast directly to int.
stream << static_cast<int>(static_cast<uint8_t>(i));
}
else
{
// No cast needed for ints wider than 8 bits.
stream << i;
}
return stream.str();
}
Resposta original que não lida com ints de 8 bits corretamente como eu pensava:
A resposta de Kornel Kisielewicz é ótima. Porém, um pequeno acréscimo ajuda a capturar casos em que você está chamando essa função com argumentos de modelo que não fazem sentido (por exemplo, flutuação) ou que resultariam em erros confusos do compilador (por exemplo, tipo definido pelo usuário).
template< typename T >
std::string int_to_hex( T i )
{
// Ensure this function is called with a template parameter that makes sense. Note: static_assert is only available in C++11 and higher.
static_assert(std::is_integral<T>::value, "Template argument 'T' must be a fundamental integer type (e.g. int, short, etc..).");
std::stringstream stream;
stream << "0x"
<< std::setfill ('0') << std::setw(sizeof(T)*2)
<< std::hex << i;
// Optional: replace above line with this to handle 8-bit integers.
// << std::hex << std::to_string(i);
return stream.str();
}
Eu editei isso para adicionar uma chamada para std :: to_string porque os tipos inteiros de 8 bits (por exemplo, std::uint8_t
valores passados) std::stringstream
são tratados como char, o que não fornece o resultado desejado. Passar esses números inteiros para std::to_string
manipulá-los corretamente e não prejudica as coisas ao usar outros tipos inteiros maiores. É claro que você pode sofrer um leve impacto no desempenho nesses casos, pois a chamada std :: to_string é desnecessária.
Nota: eu teria acabado de adicionar isso em um comentário à resposta original, mas não tenho o representante para comentar.
int
tipo;)