#include <iostream>
#include <iomanip>
#include <sstream>
#include <climits>
#include <cstdint>
#include <type_traits>
namespace hex_out_helper {
constexpr int HEX_DIGIT_BITS = 4; // One hex digit = 4 bits.
constexpr int HEX_BASE_CHARS = 2; // For the "0x".
template<typename T> struct CharCheck {
using type = T;
};
template<> struct CharCheck<signed char> {
using type = char;
};
template<> struct CharCheck<unsigned char> {
using type = char;
};
template<typename T> using CharChecker = typename CharCheck<T>::type;
} // namespace hex_out_helper
template<typename T> std::string hex_out_s(T val) {
using namespace hex_out_helper;
std::stringstream sformatter;
sformatter << std::hex
<< std::internal
<< std::showbase
<< std::setfill('0')
<< std::setw((sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) + HEX_BASE_CHARS)
<< (std::is_same<CharChecker<T>, char>{} ? static_cast<int>(val) : val);
return sformatter.str();
}
int main() {
uint32_t hexU32 = 0x0f;
int hexI = 0x3c;
unsigned short hexUS = 0x12;
char hexC = 0xf;
unsigned char hexUC = 0xa;
signed char hexSC = 0x3;
std::cout << "uint32_t: " << hex_out_s(hexU32) << std::endl;
std::cout << "int: " << hex_out_s(hexI) << std::endl;
std::cout << "unsigned short: " << hex_out_s(hexUS) << std::endl;
std::cout << "char: " << hex_out_s(hexC) << std::endl;
std::cout << "unsigned char: " << hex_out_s(hexUC) << std::endl;
std::cout << "signed char: " << hex_out_s(hexSC) << std::endl;
std::cout << "Decimal rvalues, too: " << hex_out_s(29) << std::endl;
std::cout << "And a long long: " << hex_out_s(LLONG_MAX) << std::endl;
}