Search This Blog

09 July 2009

Binary Literals

I was randomly browsing for some stuff and I stumbled across this post on binary literals. It proposed the following as an option for C++ which the article admits as being inefficient:
unsigned long const mask
= std::bitset<6>(std::string("111100")).to_ulong();


I was thinking that C++ templates must be able to offer something more efficient...
template <int N>
struct Binary
{
enum { value = Binary<N % 10> | 2 * Binary<N / 10>::value }
};

template<>
struct Binary<0>
{
enum { value = 0; }
};

template<>
struct Binary<1>
{
enum { value = 1; }
}

int foo = Binary<111100>::value;


Usual caveats apply. Code is untested and may eat kittens.

4 comments:

Thomas Guest said...

Antony, cute idea! One drawback is that the largest binary literal you can write (on a machine with 32 bit ints) would be Binary<1111111111>::value

Looks like C++0x will allow you to write e.g. 101010111000101b as a user defined literal.

Antony said...

Maybe possible to extend the supported value by using octal and long longs... so the template becomes:

template <unsigned long long N>
struct Binary
{
enum { value = Binary<N & 7>::value | 2 * Binary<N / 8>::value }
};

...

int foo = Binary<0111100>::value;

Thomas Guest said...

Antony, that's a fiendishly cunning use of octal literals, but I think it shows another flaw.

Binary<111>::value and Binary<0111>::value would be different.

Antony said...

There is a limited form of error checking: When using octal, Binary<111>::value would fail to compile because (111 & 7) == 7... and there is no specialized template for the value 7.