再帰テンプレート
正式な呼び方かどうかわかりませんが、テンプレートを再帰的に呼び出すという意味です。
プログラムには連接・選択・反復の3つの要素が必要ですが、テンプレートを使用した連接・選択は今まで見てきた通りですね。
で、最後に反復をテンプレートの再帰呼び出しで実現しようという話です。
1〜Nまでの総和
//1〜Nまでの総和を求める(一般形) template< unsigned int N > struct sum { static const unsigned int value = N + func< N - 1 >::value; }; //N==1のときの特殊化 //再帰的に呼び出すので、必ず終了条件が必要。(再帰しない特殊化バージョン) template<> struct sum< 1 > { static const unsigned int value = 1; };
実行時ではなく、コンパイル時に55が計算される
int a = sum< 10 >::value; //int a = 55;
Nの階乗
//Nの階乗を求める(一般形) template< unsigned int N > struct factorial { static const unsigned int value = N * factorial< N - 1 >::value; }; //N==1のときの特殊化 //再帰的に呼び出すので、必ず終了条件が必要。(再帰しない特殊化バージョン) template<> struct factorial< 1 > { static const unsigned int value = 1; };
実行時ではなく、コンパイル時に120が計算される
int a = factorial< 5 >::value; //int a = 120;
あまり実用的な例ではないですね。使いどころが難しいです。
よくある別の例としては、C++では2進数表記が出来ないので代用できますよと。
2進数→10進数変換
//2進数→10進数変換(一般形) template< unsigned int N > struct binary { static const unsigned int value = binary< N / 10 >::value << 1 | N % 10; }; //N==0のときの特殊化 template<> struct binary< 0 > { static const unsigned int value = 0; };
int a = binary< 1011 >::value; //int a = 11;
あまり使わないかもしれませんが、こういうことも出来ますよと。
値に対する再帰より、型に対する再帰の方が重要ですね。
CRTPやExpressionTemplateなどのイディオムが有名です。
boost::spiritにもこの2つのイディオムが使われています。