c ++ 0x: техника шаблонов Variadic - PullRequest
       19

c ++ 0x: техника шаблонов Variadic

1 голос
/ 08 сентября 2011

Я готовлюсь к определению пользовательских литералов с Variadic Template

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...>() ;
}

Ответы [ 3 ]

1 голос
/ 08 сентября 2011

На любом шаге рекурсии вы уже знаете ранг самой левой цифры.

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...>();
}
1 голос
/ 08 сентября 2011

Пакеты параметров относительно негибкие, и вы обычно не пишете алгоритмы непосредственно в них.Шаблоны функций Variadic хороши для пересылки, но я бы упаковал их в более управляемый tuple, прежде чем пытаться им манипулировать.

Используя простую метафункцию binary_string_value, где место 1 стоит первым, иобщая 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;
}
1 голос
/ 08 сентября 2011

Одна возможность будет использовать аккумулятор:

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