バイトオーダ反転、ビットオーダ反転
#include <iostream> template <int value_, typename T = int, int size = sizeof(T)> struct byte_order_reverser { enum { msb = (value_ >> ((size - 1) * 8)), other = (value_ - (msb << ((size - 1) * 8))), reverse_value = (byte_order_reverser<other, T, size-1>::reverse_value << 8) + byte_order_reverser<other, T, size-1>::msb, value = (reverse_value << 8) + msb }; }; template <int value_, typename T> struct byte_order_reverser<value_, T, 1> { enum { msb = value_, other = 0, reverse_value = 0, value = msb }; }; template <typename T, int length = sizeof(T)> struct byte_order_reverser2 { static T value(T val) { return ((val >> ((length - 1) * 8)) & 0xff) + (byte_order_reverser2<T, length-1>::value(val) << 8); } }; template <typename T> struct byte_order_reverser2<T, 1> { static T value(T val) { return val & 0xff; } }; template <int value_, typename T = int, int length = sizeof(T) * 8> struct bit_order_reverser { enum { lsb = (value_ & 1), other = ((value_ - lsb) >> 1) & ~(1 << (length - 1)), value = (lsb << (length - 1)) | bit_order_reverser<other, T, length-1>::value }; }; template <int value_, typename T> struct bit_order_reverser<value_, T, 1> { enum { lsb = 0, other = 0, value = lsb }; }; template <typename T, int length = sizeof(T)*8> struct bit_order_reverser2 { static T value(T val) { return ((val & 1) << (length - 1)) | bit_order_reverser2<T, length-1>::value( (val >> 1) & ~(1 << (length - 1))); } }; template <typename T> struct bit_order_reverser2<T, 1> { static T value(T val) { return val & 1; } }; void reverse_test() { std::cout << "int test" << std::endl; std::cout << byte_order_reverser<10>::msb << std::endl; std::cout << byte_order_reverser<10>::other << std::endl; std::cout << byte_order_reverser<10>::value << std::endl; std::cout << byte_order_reverser<byte_order_reverser<10>::value>::value << std::endl; std::cout << std::endl; std::cout << "short test" << std::endl; std::cout << byte_order_reverser<10,short>::msb << std::endl; std::cout << byte_order_reverser<10,short>::other << std::endl; std::cout << byte_order_reverser<10,short>::value << std::endl; std::cout << byte_order_reverser< byte_order_reverser<10, short>::value, short>::value << std::endl; std::cout << std::endl; } void reverse_test2() { std::cout << "int test" << std::endl; std::cout << byte_order_reverser2<int>::value(10) << std::endl; std::cout << byte_order_reverser2<int>::value( byte_order_reverser2<int>::value(10)) << std::endl; std::cout << std::endl; std::cout << "short test" << std::endl; std::cout << byte_order_reverser2<short>::value(10) << std::endl; std::cout << byte_order_reverser2<short>::value( byte_order_reverser2<short>::value(10)) << std::endl; std::cout << std::endl; } void bit_reverse_test() { std::cout << "int test" << std::endl; // 0001 0010 0011 0100 0101 0110 0111 1000 (0x12345678) // 0001 1110 0110 1010 0010 1100 0100 1000 (0x1e6a2c48) std::cout << std::hex << bit_order_reverser<0x12345678>::value << std::endl; std::cout << std::hex << bit_order_reverser<bit_order_reverser<0x12345678>::value>::value << std::endl; std::cout << "short test" << std::endl; // 0001 0010 0011 0100 (0x1234) // 0010 1100 0100 1000 (0x2c48) std::cout << std::hex << bit_order_reverser<0x1234,short>::value << std::endl; std::cout << std::hex << bit_order_reverser< bit_order_reverser<0x1234,short>::value, short >::value << std::endl; } void bit_reverse_test2() { std::cout << "int test" << std::endl; // 0001 0010 0011 0100 0101 0110 0111 1000 (0x12345678) // 0001 1110 0110 1010 0010 1100 0100 1000 (0x1e6a2c48) std::cout << std::hex << bit_order_reverser2<int>::value(0x12345678) << std::endl; std::cout << std::hex << bit_order_reverser2<int>::value( bit_order_reverser2<int>::value(0x12345678)) << std::endl; std::cout << "short test" << std::endl; // 0001 0010 0011 0100 (0x1234) // 0010 1100 0100 1000 (0x2c48) std::cout << std::hex << bit_order_reverser2<short>::value(0x1234) << std::endl; std::cout << std::hex << bit_order_reverser2<short>::value( bit_order_reverser2<short>::value(0x1234)) << std::endl; } int main() { reverse_test(); reverse_test2(); bit_reverse_test(); bit_reverse_test2(); return 0; }
コンパイル時にエンディアンの差を吸収できないかなー?と考えた結果の絞り粕です。
結局左辺値がtemplate計算では使えないことに気が付いて駄目だな、という結論に達しました。
byte_order_reverser, bit_order_reverserでは特に最適化なしで定数畳み込みされます。
byte_order_reverser2, bit_order_reverser2では最適化オプションが必要でした。
式の項たどっていって定数項・・・というか右辺値だと最適化でたたみこめるってことなんでしょうか>gcc
bool is_little_endian() { const int value = 1; return *reinterpret_cast<const char*>(&value) == 1; }
この方法ベースにして最適化でどこまでうまくたたみこめるかを考えるしかなさそうです・・・