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 時点).
もっと楽しく
二進数リテラル(嘘) - とくにあぶなくないRiSKのブログ
いいですねー.
実行時に評価するなら
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)); }