C/C++について
template<int n> struct sum1toN { enum { value = sum1toN<n - 1>::value + n }; }; template<> struct sum1toN<0> { enum { value = 0 }; }; int main() { printf("sum=%d\n", sum1toN<10>::value); return 0; }
実行すると
sum=55
と表示されます. この55はコンパイル時に決定されるので実行時には定数です.
sum1toN<3>::value
と書くと, それは
sum1toN<2>::value + 3
と展開され, 更にあと二回sum1toNが呼び出さて
sum1toN<0>::value + 1 + 2 + 3
となったところで, テンプレートの特殊化sum1toN<0>が呼び出されて停止します. 結果,
0 + 1 + 2 + 3
となり, コンパイラがこれを計算して6に置き換えます.
template<int n> struct ilog2 { enum { value = ilog2<n / 2>::value + 1 }; }; template<> struct ilog2<0> { enum { value = -1 }; };
繰り返し2で割り, もう割り切れなくなったところでテンプレートの特殊化が呼び出されます.
ilog2<1>::value ilog2<2>::value ilog2<3>::value ilog2<4>::value ilog2<5>::value ilog2<7>::value ilog2<8>::value
はそれぞれ0, 1, 1, 2, 2, 2, 3という値に置き換えられます.
template<int n> struct binary { enum { bit = n % 10, value = bit + (binary<n / 10>::value << 1) }; }; template<> struct binary<0> { enum { bit = 0, value = 0 }; };
binary<11110>::valueとすれば30となるわけですな.
template<int x> struct positive_float_int2binary { enum { log2_x = ilog2<x>::value, exponent = (log2_x + 127) << 23, f = x - (1 << log2_x), mantissa = (log2_x <= 23) ? (f << (23 - log2_x)) : (unsigned(f) >> (log2_x - 23)), value = exponent | mantissa }; };
例2で作ったilog2を使っています. 名前がいまいちですが, まあ気にしない. 与えられた自然数xに対してx-ilog2<x>が浮動小数表現としての仮数部になります. 浮動小数の格納形式も参考にしていただければ. float型の制約上224あたりが限界です. コード内では負数などにも対応できるよう拡張しています.