Помогите с шаблонизирующей функцией byteswapping, производительность снижается? - PullRequest
4 голосов
/ 03 февраля 2011
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 <4>, когда мне нужно вызвать byteswap <2>, но со ссылкой.

Любая идея, какчтобы это выглядело красиво?Возможно ли добиться этого (используя встраивание или другие приемы), чтобы сделать его таким же быстродействующим, как и непосредственное выполнение битовых операций?

Ответы [ 4 ]

4 голосов
/ 03 февраля 2011

Вот как я бы его кодировал:

#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
}

другими словами, я бы не использовал размер в качестве параметра шаблона, как вы это делали.

EDIT
извините, мой первый код был явно неправильным в обмене wrt / uint32.

2 голосов
/ 03 февраля 2011

Заимствование из некоторого кода :

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;
}
0 голосов
/ 03 февраля 2011

я думаю, что вы концептуально не правы в определениях byteswap (2) и byteswap (4). я не думаю, что то, как вы определили это правильно, относится к URL http://www.iis.sinica.edu.tw/~kathy/vcstl/templates.htm#T6

0 голосов
/ 03 февраля 2011

Я перепишу это так:

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...