Grazie al commento di Lincoln qui sotto, ho cambiato questa risposta.
La risposta seguente gestisce correttamente gli int a 8 bit in fase di compilazione. Tuttavia, richiede C ++ 17. Se non hai C ++ 17, dovrai fare qualcos'altro (ad esempio fornire overload di questa funzione, uno per uint8_t e uno per int8_t, o usare qualcosa oltre a "if constexpr", forse 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();
}
Risposta originale che non gestisce correttamente gli int a 8 bit come pensavo:
La risposta di Kornel Kisielewicz è ottima. Ma una leggera aggiunta aiuta a catturare i casi in cui stai chiamando questa funzione con argomenti del modello che non hanno senso (es. Float) o che comporterebbero errori di compilazione disordinati (es. Tipo definito dall'utente).
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();
}
Ho modificato questo per aggiungere una chiamata a std :: to_string perché i tipi interi a 8 bit (ad esempio i std::uint8_t
valori passati) a std::stringstream
sono trattati come char, che non ti dà il risultato desiderato. Passando tali numeri interi astd::to_string
gestirli correttamente e non danneggia le cose quando si usano altri tipi interi più grandi. Ovviamente potresti subire un leggero calo delle prestazioni in questi casi poiché la chiamata std :: to_string non è necessaria.
Nota: avrei semplicemente aggiunto questo in un commento alla risposta originale, ma non ho il rappresentante per commentare.
int
tipo;)