C ++ 0x: метод варидового шаблона
-
27-10-2019 - |
Вопрос
Я готовлюсь к определению Пользовательские литералы с Вариационный шаблон
template<...>
unsigned operator "" _binary();
unsigned thirteen = 1101_binary;
GCC 4.7.0 не поддерживает operator ""
Тем не менее, но я могу имитировать это с простой функцией до тех пор.
Увы, моя рекурсия - неправильный путь. Я не могу придумать хорошего способа, как я Не сдвигайте самые правые значения, но самые левые:
template<char C> int _bin();
template<> int _bin<'1'>() { return 1; }
template<> int _bin<'0'>() { return 0; }
template<char C, char D, char... ES>
int _bin() {
return _bin<C>() | _bin<D,ES...>() << 1; // <-- WRONG!
}
Что, конечно, не совсем правильно:
int val13 = _bin<'1','1','0','1'>(); // <-- gives 10
Потому что моя рекурсия смещается с самого правого »1, а не самые левые.
Это, наверное, я крошечная вещь, но я просто не вижу этого.
- Могу ли я исправить линию
_bin<C>() | _bin<D,ES...>() << 1;
? - Или мне нужно все пересылать и перевернуть все потом (не хорошо)?
- Или какой -либо другой способ, который я не могу увидеть?
Обновлять: Я не мог сложить рекурсию наоборот, но я обнаружил sizeof...
. Анкет Работает, но не идеально. Есть другой способ?
template<char C, char D, char... ES>
int _bin() {
return _bin<C>() << (sizeof...(ES)+1) | _bin<D,ES...>() ;
}
Решение
На любом одном этапе рекурсии вы уже знаете звание самой левой цифры.
template<char C> int _bin();
template<> int _bin<'1'>() { return 1; }
template<> int _bin<'0'>() { return 0; }
template<char C, char D, char... ES>
int _bin() {
return _bin<C>() << (1 + sizeof...(ES)) | _bin<D,ES...>();
}
Другие советы
Пакеты параметров относительно негибкие, и вы обычно не пишите алгоритмы непосредственно в них. Вариальные шаблоны функций хороши для пересылки, но я бы упаковал в более управляемый tuple
Прежде чем пытаться манипулировать этим.
Используя простой binary_string_value
Метафункция, где на первом месте есть место, и общая tuple_reverse
Метафункция, шаблон будет
template< char ... digit_pack >
constexpr unsigned long long _bin() {
typedef std::tuple< std::integral_constant< digit_pack - '0' > ... > digit_tuple;
return binary_string_value< typename tuple_reverse< digit_tuple >::type >::value;
}
Одной из возможностей будет использование аккумулятора:
template <char C>
int _binchar();
template<>
int _binchar<'0'>() { return 0; }
template<>
int _binchar<'1'>() { return 1; }
template<char C>
int _bin(int acc=0) {
return (acc*2 + _binchar<C>());
}
template<char C, char D, char... ES>
int _bin(int acc=0) {
return _bin<D, ES...>(acc*2 + _binchar<C>());
}