unsigned int binary(unsigned int value)
{
unsigned int ret = 0 ;
for (int i = 0; value != 0; ++i )
{
ret |= value%10 << i;
value /= 10 ;
}
return ret ;
}
int main()
{
std::cout << binary(101010) << std::endl ; // 42
char buf[ binary(101010) ] ; // エラー
}
しかし、実行時に計算するのは、問題がある。C99でないと、配列を確保できないからだ。ここで必要なのは、コンパイル時の定数なのだ。
1.3 コンパイル時計算
そこで、テンプレートの出番だ。
template < unsigned int N >
struct binary
{
static unsigned int const value = binary< N/10 >::value << 1 | N%10 ;
} ;
template < >
struct binary<0>
{
static unsigned int const value = 0 ;
} ;
int main()
{
std::cout << binary<101010>::value << std::endl ;
char buf[ binary<101010>::value ] ;
}
テンプレートを、再帰的に呼んでいる。どのように実体化されるかというと、
binary<101010>
binary<10101>
binary<1010>
binary<101>
binary<10>
binary<1>
binary<0>
0になったところで、特殊化が働き、この再帰的なループは終わる。そう、コンパイラに、テンプレートで計算させているわけだ。ループには再帰を、条件分岐には特殊化を使う。再帰に親しいプログラマならば、簡単にこのコードが理解できるはずだ。この手法を用いれば、フィボナッチ数や素数も計算できる。これは、数値に対する計算だ。
さて、とりあえずここまで書いた。この次は型に対する計算を書かなければ。具体的に説明するには、やはりiter_swapのようなものを実装していくのが一番だろう。C++ Template Metaprogrammingは実によくできている。
good job.
ReplyDeletepart2も楽しみにしてます。