2011-02-03 30 views
4
template<int size> 
inline void* byteswap(void* __x); 

template<> 
inline void* byteswap<2>(void* __x) 
{ 
    return (*(uint16*)__x >> 8) | (*(uint16*)__x << 8); 
} 

template<> 
inline void* byteswap<4>(void* __x) 
{ 
    return (byteswap<4>(__x & 0xffff) << 16) | (bswap_16 (__x >> 16)); 
} 

template<typename T> 
inline T byteswap(T& swapIt) 
{ 
    return (T*)byteswap<sizeof(T)>(swapIt); 
}  

int main() { 
    uint32 i32 = 0x01020304; 
    uint16 i16 = 0x0102; 

    byteswap(i32); 
    byteswap(i16); 

    return 0; 
} 

以上显然甚至没有编译。我很困惑,因为看起来我需要void *作为函数的参数,而且事情有点让人难以接受,当我需要调用byteswap < 2>但带有引用时。帮助模板化byteswapping功能,性能如何?

任何想法如何让这看起来很漂亮?它是否有可能实现(使用内联或其他技巧)使其像直接执行位操作一样具有性能?

+1

不要使用两个前导下划线,它们是保留的! – Simone 2011-02-03 14:35:59

+0

哥们,弗雷德,你到处都是! – chriskirk 2011-02-03 14:46:53

回答

4

这是我怎么想它的代码:

#include <iostream> 

typedef unsigned short uint16; 
typedef unsigned int uint32; 

template<typename T> T byteswap(T value); 

template<> 
uint16 byteswap<uint16>(uint16 value) 
{ 
    return (value >> 8)|(value << 8); 
} 

template<> 
uint32 byteswap<uint32>(uint32 value) 
{ 
    return uint32(byteswap<uint16>(value) << 16) | byteswap<uint16>(value >> 16); 
} 

int main() { 
    uint32 i32 = 0x11223344; 
    uint16 i16 = 0x2142; 

    std::cout << std::hex << byteswap(i32) << std::endl; // prints 44332211 
    std::cout << std::hex << byteswap(i16) << std::endl; // prints 4221 
} 

换句话说,我不会用大小为模板参数,你在干什么。

编辑
对不起,我的第一个代码是完全错误的WRT/UINT32交换。

0

我会改写这样的:

template < size_t size > 
inline void sized_byteswap(char* data); 

template <> 
inline void sized_byteswap<2>(char* data) 
{ 
    uint16_t* ptr = reinterpret_cast<uint16_t*>(data); 
    *ptr = (*ptr >> 8)|(*ptr << 8); 
} 

template <> 
inline void sized_byteswap<4>(char* data) 
{ 
    uint32_t* ptr = reinterpret_cast<uint32_t*>(data); 
    *ptr = (*ptr >> 24)|((*ptr & 0x00ff0000) >> 8)|((*ptr & 0x0000ff00) << 8)|(*ptr << 24); 
} 

template < typename T > 
T byteswap(T value) 
{ 
    sized_byteswap< sizeof(T) >(reinterpret_cast<char*>(&value)); 
    return value; 
} 

int main() 
{ 
    uint32 i32 = byteswap(uint32(0x01020304)); 
    uint16 i16 = byteswap(uint16(0x0102)); 

    return 0; 
} 
2

Borrowing from some code

template<int N> 
void byteswap_array(char (&bytes)[N]) { 
    // Optimize this with a platform-specific API as desired. 
    for (char *p = bytes, *end = bytes + N - 1; p < end; ++p, --end) { 
    char tmp = *p; 
    *p = *end; 
    *end = tmp; 
    } 
} 

template<typename T> 
T byteswap(T value) { 
    byteswap_array(*reinterpret_cast<char (*)[sizeof(value)]>(&value)); 
    return value; 
}