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あたりが限界です. コード内では負数などにも対応できるよう拡張しています.