Вопрос

Я готовлюсь к определению Пользовательские литералы с Вариационный шаблон

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>());
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top