Наскоро докато ровех из нета срещнах идеята за user defined literal _bits, а днес ми остана време да го напиша.
В общи линии, идеята е safe & fast обръщане на двоично число в десетично, например на 11000100 в 196, без намесата на програмист.
Ето и въпросния код.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
typedef unsigned long long uint64; //compile time big endian to unsigned long long template<char head, char... tail> struct big_endian_to_uint { static_assert(head >= '0' && head <='1', "Invalid bits in operator\"\"_bits big_endian_to_uint<>"); const static uint64 value = (head - '0') + 2 * (big_endian_to_uint<tail...>::value); }; template<char head> struct big_endian_to_uint<head> { static_assert(head >= '0' && head <='1', "Invalid bits in operator\"\"_bits big_endian_to_uint<>"); const static uint64 value = (head - '0'); }; //************************************** //compile time little endian to unsigned long long template<char head, char... tail> struct little_endian_to_uint { static_assert(head >= '0' && head <='1', "Invalid bits in operator\"\"_bits little_endian_to_uint<>"); const static uint64 value = (1 << sizeof...(tail)) * (head - '0') + (little_endian_to_uint<tail...>::value); }; template<char head> struct little_endian_to_uint<head> { static_assert(head >= '0' && head <='1', "Invalid bits in operator\"\"_bits little_endian_to_uint<>"); const static uint64 value = (head - '0'); }; //************************************** template<char... chars> constexpr uint64 operator"" _bits(){ //endianess check available /*const static int i = 1; const static char c = * ((char *)(&i)); const static bool is_little_endian = i == c; if (is_little_endian) return little_endian_to_uint<chars...>::value; else return big_endian_to_uint<chars...>::value; */ return little_endian_to_uint<chars...>::value; } int main(){ std::cout << 101010_bits; } |
С този оператор, можем да пишем неща като int i = 1000_bits; и i ще има стойност 8.
Става compile time, прави проверки за валидност, намалява възможноста за някои грешки, а и се чете лесно :).
Може да си спестиш малко повтаряне на логика, ако base case-ът ти е празен стринг:
template struct little_endian_to_uint;
template
struct little_endian_to_uint {
static_assert(head >= ‘0’ && head <='1', "Invalid bits in operator\"\"_bits little_endian_to_uint”);
const static uint64 value = (1 << sizeof…(tail)) * (head – '0') +
(little_endian_to_uint::value);
};
template
struct little_endian_to_uint {
const static uint64_t value = 0;
};
@Иван – може и така.
Thanks2Komitov за constexpr.
🙂