テンプレートの特殊化

なんとなく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:特定の定数等を指定して、その場合の実装を用意するみたいなこと