C++

ふくしゅう。 http://exe.adam.ne.jp/j/tmfd.html から。

template <int x> struct Square
{
    enum { value = x * x};
};

int main()
{
    std::cout << Square::<16>::value << std::endl;
}

このコードだと実行時に計算が行われず、コンパイル時に計算される。マクロだと思えば良い。これを「定数の畳み込み」というらしい。

次、「ループ展開」。お題はビットフラグ。順に << したビット値が並ぶ定数がある。

#define	BIT_ONE	  0x0001
#define	BIT_TWO	  0x0002
#define	BIT_THREE 0x0004
#define	BIT_FOUR  0x0008

もうなんとなくわかるはず。こいつらをコンパイル時にループで定義しちまおうという話。 勉強だから自分で書いてみる。

/* BitFlagVector.h */
#pragma once

/**
 * 先に部分特殊化を行うための前方宣言をする
 * テンプレートクラス本体の定義後で特殊化する場合は要らないんだって
 */
template <int n> struct BitFlags;

/**
 * 具体的なパラメータ (0) によるテンプレートの部分特殊化
 * テンプレートパラメータに 0 が指定された場合にこの定義が適用される
 */
template <>
struct BitFlags<0>
{
  enum {value = 0};
};

/**
 * ビットフラグの値を示すテンプレート
 * 1 を << していく
 */ 
template <int n>
struct BitFlags
{
  enum {value = 1 << (n - 1)};
};

template <typename T>
struct BitFlagsVector
{
  volatile T  data_;

  BitFlagsVector() : data_(0) {}

  template <int i>
  void on()
  {
    data_ |= BitFlags<i>::value;
  }

  template <int i>
  void off()
  {
    data_ &= ~BitFlags<i>::value;
  }

  template <int i>
  bool is() const
  {
    return data_ & BitFlags<i>::value;
  }

  void reset()
  {
    data_ = 0;
  }
};

typedef BitFlagsVector<UInt32>	BitFlagsVector32;

これを利用するとき。

class poo
{
  BitFlagsVector32  bits_;
public:
  enum Bits
  {
    None,
    BitOne,
    BitTwo,
    BitThree,
    BitFour
  };

  bool Something()
  {
    bits_.on<Bits::BitThree>();
    bits_.off<Bits::BitOne>();

    return bits.is<BitFour>();
  }
};

実際にビルドしないとな〜