我想发布基于@FredOverflow的重新发明版本。我进行了以下修改。
固定:
- Rhs
operator<<
应该是const
参考类型。在@FredOverflow的代码中,h.x >>= 4
更改了output h
,令人惊讶的是它与标准库不兼容,并且将类型T
重新排序为可复制构造的。
- 假设仅
CHAR_BITS
是4的倍数。@FredOverflow的代码假定char
是8位,这在DSP的某些实现中并不总是正确的,尤其char
是16位,24位,32位等并不罕见。。
提高:
- 支持所有其他可用于整数类型的标准库操纵器,例如
std::uppercase
。由于在中使用了格式输出_print_byte
,因此标准库操纵器仍然可用。
- 添加
hex_sep
以打印单独的字节(请注意,在C / C ++中,“字节”根据定义是一个存储单元,大小为char
)。添加一个模板参数Sep
和实例_Hex<T, false>
,并_Hex<T, true>
在hex
和hex_sep
分别。
- 避免二进制代码膨胀。函数
_print_byte
是operator<<
通过函数参数 提取出来的,size
避免对不同的实例化Size
。
有关二进制代码膨胀的更多信息:
如改进3所述,无论使用hex
和hex_sep
使用的广泛程度,只有(几乎)重复函数的两个副本将以二进制代码退出:_print_byte<true>
和_print_byte<false>
。您可能已经意识到,也可以使用完全相同的方法消除这种重复:添加一个function参数sep
。是的,但是如果这样做,if(sep)
则需要运行时。我想要一个可以在程序中广泛使用的通用库实用程序,因此我在复制而不是运行时开销方面妥协了。我是通过使用compile-time来实现的if
:C ++ 11 std::conditional
,希望可以通过来优化函数调用的开销inline
。
hex_print.h:
namespace Hex
{
typedef unsigned char Byte;
template <typename T, bool Sep> struct _Hex
{
_Hex(const T& t) : val(t)
{}
const T& val;
};
template <typename T, bool Sep>
std::ostream& operator<<(std::ostream& os, const _Hex<T, Sep>& h);
}
template <typename T> Hex::_Hex<T, false> hex(const T& x)
{ return Hex::_Hex<T, false>(x); }
template <typename T> Hex::_Hex<T, true> hex_sep(const T& x)
{ return Hex::_Hex<T, true>(x); }
#include "misc.tcc"
hex_print.tcc:
namespace Hex
{
struct Put_space {
static inline void run(std::ostream& os) { os << ' '; }
};
struct No_op {
static inline void run(std::ostream& os) {}
};
#if (CHAR_BIT & 3)
#error "hex print utility need CHAR_BIT to be a multiple of 4"
#endif
static const size_t width = CHAR_BIT >> 2;
template <bool Sep>
std::ostream& _print_byte(std::ostream& os, const void* ptr, const size_t size)
{
using namespace std;
auto pbyte = reinterpret_cast<const Byte*>(ptr);
os << hex << setfill('0');
for (int i = size; --i >= 0; )
{
os << setw(width) << static_cast<short>(pbyte[i]);
conditional<Sep, Put_space, No_op>::type::run(os);
}
return os << setfill(' ') << dec;
}
template <typename T, bool Sep>
inline std::ostream& operator<<(std::ostream& os, const _Hex<T, Sep>& h)
{
return _print_byte<Sep>(os, &h.val, sizeof(T));
}
}
测试:
struct { int x; } output = {0xdeadbeef};
cout << hex_sep(output) << std::uppercase << hex(output) << endl;
输出:
de ad be ef DEADBEEF