読者です 読者をやめる 読者になる 読者になる

とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

二進数リテラル(嘘)

ネタ。二進数リテラルのライブラリ実装。
定数としてコンパイル時に評価されます。 + が 1, - が 0 を表します。b() プレフィックスをつけると二進数として扱われます。

#include<cstddef>

namespace sscrisk{ namespace detail{

  template<class T>
  constexpr T pow(T x, std::size_t y){
   return y == 0 ? 1
    : y == 1 ? x
    : x * pow(x, y - 1);
  }

  template<class T = int, std::size_t N = 0>
  class binary
  {
   T value;
  public:
   constexpr binary()
    : value()
   {}
   constexpr binary(T value)
    : value(value)
   {}
   constexpr binary<T, N + 1> operator+()const{ return {value + pow(2, N)}; }
   constexpr binary<T, N + 1> operator-()const{ return {value}; }
   constexpr binary<T, N + 2> operator++()const{ return {value + pow(2, N) + pow(2, N + 1)}; }
   constexpr binary<T, N + 2> operator--()const{ return {value}; }
   constexpr operator T()const{ return value; }
  };

 }

 template<class T = int>
 constexpr detail::binary<T, 0> b(){ return {}; }

}


#include<iostream>
#include<cassert>

int main()
{
 using sscrisk::b;

 {
  constexpr auto w = +b();
  assert(w == 1);
  constexpr auto x = -b();
  assert(x == 0);
  constexpr auto y = ++b();
  assert(y == 3);
  constexpr auto z = --b();
  assert(z == 0);
 }

 std::cout <<     -b() << std::endl;
 std::cout <<     +b() << std::endl;
 std::cout <<    +-b() << std::endl;
 std::cout <<    ++b() << std::endl;
 std::cout <<   +--b() << std::endl;
 std::cout <<   +-+b() << std::endl;
 std::cout <<   ++-b() << std::endl;
 std::cout <<   +++b() << std::endl;
 std::cout <<  +---b() << std::endl;
 std::cout <<  +--+b() << std::endl;
 std::cout <<  +-+-b() << std::endl;
 std::cout <<  +-++b() << std::endl;
 std::cout <<  ++--b() << std::endl;
 std::cout <<  ++-+b() << std::endl;
 std::cout <<  +++-b() << std::endl;
 std::cout <<  ++++b() << std::endl;
 std::cout << +----b() << std::endl;
}

実行結果:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16