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は実によくできている。
 
 
1 comment:
good job.
part2も楽しみにしてます。
Post a Comment