2006-08-27
近況
また余暇コードを書きはじめた. 挫けないようゴールは小物をえらぶ. こんどは C++ を使っている. 趣味での C++ はちょっと久々. ほどよくモダンに書きたい.
作業をすすめると, ある整数値の二進対数を計算したくなった. lg(512) -> 9 みたいなやつ. 端数は切り上げたい. (ex. lg(100) -> 7) 想像のつくとおり, ビットシフトでせこく計算を端折ったり, メモリをけちる都合で適当にデータやメモリブロックの大きさを揃えるような目的に使う. だから対数を求めたら逆に 2 の指数も計算したい (ex. pow(2, 7) -> 128)
モダン界に生きる以上, このサイズ計算はコンパイル時にやる必要がある. こんなかんじ.
typename<typename S>
struct PoormansContainer {
enum {
block_size = ... sizeof(S)を使った式 ..., // ここで指数を計算
block_power = ... sizeof(S)を使った式 ... // ここで対数を計算
};
...
};
...
PoormansContainer<MyData> data_list;
中年からのメタプロデビュー
C++ でコンパイル時計算といえば template meta programming.
せっかくだからここらでメタプロデビューをしてみようと思い
Boost MPL のドキュメント を眺めてみる.
が, むずかしい. よくわかんない. 眠い. 挫けた...
私が最初に テンプレートを使った MP を知ったのは, 学生の頃 Generative Programming という本を読んだ時のこと. たぶんこのころ瞬間的に boost をウォッチしていて, この本がメーリングリストか何かで紹介されていたのだった気がする. (よっぽどヒマだったんだね...) こいつはすごいとさっそく手元の VC++6.0 で書いてみたらさっぱり動かなかった. ひどくがっかりしたのを覚えている. それ以来 MP には近づいていない.
その時の記憶が確かなら, テンプレートの MP とはテンプレートの特殊化で分岐を, enum で変数を, 再帰的なテンプレートクラスのインスタンス化で関数を表現する手法だった気がする. boost MPL はもっと色々やっていそうだが, 私の知る素朴な MP はそんなものだった. まあ分岐と変数と関数があればなんとかなりそうだ.
ということで書いてみた:
#include <iostream>
/*
* conditional
*/
template<bool P, size_t X, size_t Y>
struct select_t { enum { value = 0 }; };
template<size_t X, size_t Y>
struct select_t<true, X, Y> { enum { value = X }; };
template<size_t X, size_t Y>
struct select_t<false, X, Y> { enum { value = Y }; };
/*
* binary logarithm (with round-up)
*/
template<size_t N, size_t M=30u> struct lg_t {
enum {
X = N & (1<<M),
Y = N & ((1<<M)-1),
value = select_t<(0 != X),
(M + select_t<(0 != Y), 1, 0>::value),
lg_t<N, M-1>::value
>::value
};
};
template<size_t N> struct lg_t<N, 0> {
enum { value = 0 };
};
/*
* power function
*/
template<size_t N, size_t M> struct pow_t {
enum {
X = M-1,
value = select_t<(0 == X),
N,
(N*pow_t<N, M-1>::value)
>::value
};
};
template<size_t N> struct pow_t<N, 0> {
enum { value = 1 };
};
int main() {
std::cout << lg_t<100>::value << std::endl;
std::cout << pow_t< 2, lg_t<100>::value >::value << std::endl;
return 0;
}
結果:
7 128
なんとなく動いてる気がする. 最近のコンパイラ(gcc-4.0)はエライ.
それにしても, このくらい誰かが既に作っているとおもうんだどなあ. boost MPL の難しさを考えると, この程度なら MP な人には当たり前すぎる話なんだろうか. 本 も出ていることだし勉強しておいた方がいいのかもと 思うも食指の動きは鈍くカート投入には至らず... それにこの再帰に満ちた界隈で生きていくには, MP 以前に関数型言語の一つも やっておいた方がよさそう. 先は長い.