テンプレートの特殊化
なんとなくC++のテンプレートで遊んだ。
よく見かける階乗を求めるプログラムです。
#include <iostream> using std::cout; using std::endl; template<int value> int func(); template <> int func<1>() { return 1; } template <int value> int func() { return value * func<value-1>(); } int main() { cout << "func<5>() = " << func<5>() << endl; // 非定数をテンプレート引数にすることは出来ない //for( int i=1; i<100; i++ ) // cout << "func<"<< i <<">() = " << func<i>() << endl; return 0; }
これだけではなんなんで指定された値を割り切ることの出来る、もっとも大きい値(ただし指定された値は除く)を求めるプログラムをつくってみました。
#include <iostream> using namespace std; // 部分的な一般化のテスト // a を割り切れる b 以下の値を取得する template< int a, int b > struct Test; template< int a > struct Test< a, 1 > { static const int value = 1; }; template< int a, int b > struct Test { static const int value = (a%b==0) ? b : Test< a, b-1 >::value; }; // a を割り切れる a 以下の数でもっとも大きい値を取得する。 template< int a > struct Test2 { static const int value = Test< a, a-1 >::value; }; int main() { cout << "Test2<21>::value = " << Test2<21>::value << endl; return 0; }
↑を実行すると 21 を割り切ることの出来る最も大きい数である 7 が表示されます。
テンプレート引数の特殊化*1は使ったことあったのですが、部分的な特殊化(って呼ぶのかはしらないですが)は初めて使ってみました。
以下の部分が、部分的な特殊化です。
template< int a > struct Test< a, 1 > { static const int value = 1; };
↑もともと構造体 Test は int a と int b というテンプレート引数を持っていたのですが、b の値が 1 の場合のみ異なる実装を適用することが出来ます。
当初、構造体ではなく関数テンプレートで実現しようとしたらコンパイルできませんでした。関数テンプレートだと部分的な特殊化ってできないのだろうか・・・?
C++のテンプレート周りは素人レベルなので、上記内容には誤りが含まれているかも知れません(w
*1:特定の定数等を指定して、その場合の実装を用意するみたいなこと