Mic*_*kLH 4 c++ templates endianness specialization template-specialization
我开发了一个简单的模板函数来交换单个字段的字节顺序:
template <typename T> inline void SwapEndian(T& ptr) {
char *bytes = reinterpret_cast<char*>(&ptr);
int a = sizeof(T) / 2;
while (a--) {
char tmp = bytes[a];
int b = sizeof(T) - 1 - a;
bytes[a] = bytes[b];
bytes[b] = tmp;
}
}
Run Code Online (Sandbox Code Playgroud)
我会经常在T = int
或float
.这两种类型在目标平台上由4个字节表示,并且可以由模板的相同特化处理.
因为这个函数有时负责处理原始数据的大缓冲区,所以我创建了一个优化的特化:
template<> inline void SwapEndian(float& ptr) {
#if defined(__GNUC__)
*reinterpret_cast<unsigned*>(&ptr) = __builtin_bswap32(*reinterpret_cast<unsigned*>(&ptr));
#elif defined(_MSC_VER)
*reinterpret_cast<unsigned*>(&ptr) = __byteswap_ulong(*reinterpret_cast<unsigned*>(&ptr));
#endif
}
Run Code Online (Sandbox Code Playgroud)
这个专门化也适用于32位整数,有符号或无符号,所以我有一大堆重复,只有类型名称不同.
如何通过这个模板路由所有4字节POD类型的实例?(PS.我愿意以不同的方式解决这个问题,但在这种情况下,我想明确知道是否可以构建这些元专用模板.)
编辑:谢谢大家,在阅读了答案并意识到算术比pod更好的限制之后,我受到了启发,写了一些东西.所有答案都很有用,但我只能接受一个,所以我接受了一个似乎在结构上相同的答案.
template<bool, bool> struct SwapEndian_ { template<typename T> static inline void _(T&); };
template<> template<typename T> inline void SwapEndian_<true, true>::_(T& ptr) {
// ... stuff here ...
}
// ... more stuff here ...
template<typename T> inline void SwapEndian(T& ptr) {
static_assert(is_arithmetic<T>::value, "Endian swap not supported for non-arithmetic types.");
SwapEndian_<sizeof(T) & (8 | 4), sizeof(T) & (8 | 2)>::template _<T>(ptr);
}
Run Code Online (Sandbox Code Playgroud)
如有疑问,请发送标签.
这个实现有两个特点 - is_pod
和get_sizeof_t
.基本覆盖将调度为SwapEndian
具有标记的两个特征的s.对于非pod类型is_pod
,还有一个覆盖和覆盖(我建议=delete
).
扩展到新的特征和类型相对容易.
template<size_t n>
using sizeof_t = std::integral_constant<size_t, n>;
template<class T>
using get_sizeof_t = sizeof_t<sizeof(T)>;
template <class T>
void SwapEndian(T& t, std::true_type /*is pod*/, sizeof_t<4>) {
std::cout << "4 bytes!\n";
// code to handle 32 bit pods
}
template <class T, size_t n>
void SwapEndian(T& t, std::true_type /*is pod*/, sizeof_t<n>) {
std::cout << "pod\n";
// code to handle generic case
}
template <class T, size_t n>
void SwapEndian(T& t, std::false_type /*is pod*/, sizeof_t<n>) {
std::cout << "not pod\n";
// probably want to =delete this overload actually
}
template<class T>
void SwapEndian(T& t) {
SwapEndian(t, std::is_pod<T>{}, get_sizeof_t<T>{});
}
Run Code Online (Sandbox Code Playgroud)
我不确定这是不是一个好主意,但上面应该这样做.
使用一些C++ 14功能.假设CHAR_BIT
是8
.
您应该很少专门化模板功能.而是超载.标签调度为您提供了重载解析功能,可以调度在编译时运行的代码.
归档时间: |
|
查看次数: |
483 次 |
最近记录: |