1

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...>() ;
}
towi
  • 21,587
  • 28
  • 106
  • 187

3 Answers3

1

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>());
}
jpalecek
  • 47,058
  • 7
  • 102
  • 144
1

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...>();
}
Luc Danton
  • 34,649
  • 6
  • 70
  • 114
1

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;
}
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421