Используйте класс манипулятора:
struct hex_format {
std::uint8_t number;
hex_format(std::uint8_t x)
:number{x}
{
}
};
Затем определите соответствующий оператор:
template <typename CharT, typename Traits>
decltype(auto) operator<<(std::basic_ostream<CharT, Traits>& os, hex_format rhs)
{
return os << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(x);
}
Не по теме: фактически это глобально изменит состояниепоток и повлиять на последующие операции потока. Вы можете исправить это, сохранив состояние:
template <typename CharT, typename Traits>
decltype(auto) operator<<(std::basic_ostream<CharT, Traits>& os, hex_format rhs)
{
auto flags = os.flags();
os << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(x);
os.flags(flags);
return os;
}