C++ で 2 進数を書く

BOOST_BINARY を使う

やっぱり基本はマクロですね.ある車輪は使いましょう.

#include <boost/utility/binary.hpp>
#include <boost/static_assert.hpp>

BOOST_STATIC_ASSERT((BOOST_BINARY(1001 1100 1011 111) == 0x4E5F));

テンプレートを使う

C++ と言えばテンプレートメタプログラミング.あまり大きな数を扱えないのが難点.

#include <boost/static_assert.hpp>

template <unsigned long N>
struct binary
{
    BOOST_STATIC_ASSERT((N % 10 == 0 || N % 10 == 1));
    static const unsigned long value = binary<N / 10>::value * 2 + N % 10;
};

template <>
struct binary<0>
{
    static const unsigned long value = 0;
};

BOOST_STATIC_ASSERT((binary<11001>::value == 25));

constexpr を使う

ここからは C++11 限定.コンパイル時にも実行時にも使えるのが constexpr 関数の素晴らしいところです.

#include <iostream>
#include <stdexcept>
 
template <class Char>
constexpr unsigned long long binary_impl(Char const *s, Char zero, Char one, unsigned long long acc)
{
    return *s == Char('\0') ?
        acc :
        binary_impl(
            s + 1,
            zero, one,
            (acc << 1) + (*s == zero ? 0 : *s == one ? 1 : throw std::invalid_argument("binary")));
}

template <class Char>
constexpr unsigned long long binary(Char const *s, Char zero = Char('0'), Char one = Char('1'))
{
    return binary_impl(s, zero, one, 0);
}

static_assert(binary("1110001110110110") == 0xE3B6, "");

ユーザー定義リテラル

いらない子と言われて久しいですが,コンパイル時に評価されることが保証されていれば,少しは役に立ったかもしれません (正規表現リテラルの誤りをコンパイル時に検出するとか).

#include <type_traits>

template <unsigned long long acc, char ...cs>
struct binary_impl
  : std::integral_constant<unsigned long long, acc>
{};

template <unsigned long long acc, char c, char ...cs>
struct binary_impl<acc, c, cs...>
  : binary_impl<(acc << 1) + (c == '0' ? 0 : c == '1' ? 1 : throw), cs...>
{};

template <char ...cs>
constexpr unsigned long long operator "" _b()
{
    return binary_impl<0, cs...>::value;
}

static_assert(11001_b == 25, "");

コンパイルは通してないのでミスがあるかもしれません.そもそもユーザー定義リテラルを実装した処理系がないのですが (2011/09 時点).

実行時に評価するなら

boost::dynamic_bitset などが使えます.C++03 でも OK.

#include <string>
#include <boost/dynamic_bitset.hpp>
#include <cassert>

int main()
{
    assert((boost::dynamic_bitset<>(std::string("1010")).to_ulong() == 10));
}