سؤال

I am preparing myself for the defintion of user-defined literals with a Variadic Template

template<...>
unsigned operator "" _binary();

unsigned thirteen = 1101_binary;

GCC 4.7.0 does not support operator "" yet, but I can simulate this with a simple function until then.

Alas, my recursion is the wrong way around. I can not think of a nice way how I do not shift the rightmost values, but the leftmost:

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!
}

which of course is not quite right:

int val13 = _bin<'1','1','0','1'>();  // <-- gives 10

because my recursion shifts the rightmost '1's farthest, and not the leftmost ones.

It is probably I tiny thing, but I just can not see it.

  • Can I correct the line _bin<C>() | _bin<D,ES...>() << 1;?
  • Or do I have to forward everything and turn it around everything afterwards (not nice)?
  • Or any other way that I can not see?

Update: I could not fold the recursion the other way around, but I discovered sizeof.... Works, but not perfect. Is there another way?

template<char C, char D, char... ES>
int _bin() {
    return   _bin<C>() << (sizeof...(ES)+1) | _bin<D,ES...>() ;
}
هل كانت مفيدة؟

المحلول

At any one step of the recursion you already know the rank of the leftmost digit.

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

نصائح أخرى

Parameter packs are relatively inflexible, and you don't usually write algorithms directly in them. Variadic function templates are good for forwarding, but I'd get that packed into a more manageable tuple before trying to manipulate it.

Using a simple binary_string_value metafunction where the 1's place comes first, and a generic tuple_reverse metafunction, the pattern would be

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;
}

One possibility would be using an accumulator:

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