テンプレートメタプログラミング

C++テンプレートテクニック 4-1、4-2


テンプレートのインスタンス化を利用して、コンパイル時にプログラミングをすることをテンプレートメタプログラミングという。

#include <iostream>
using std::cout; using std::endl;

template<int N>
class CClass {
public:
    static const int value = N;
};

int main () {
    cout << CClass<100>::value << endl;
    return 0;
}
$ main
100

このコードは、インスタンス化されると

int main () {
    cout << 100 << endl;
    return 0;
}

に置き換わります。

これだけだとだからどうした?みたいな話ですが、再帰テンプレートを利用することで面白いことができます。

1から与えられた数値までを加算した結果を返す再帰テンプレートを実装してみましょう。

#include <iostream>
using std::cout; using std::endl;
 
template<int N>
class CSum {
public:
    static const int value = N + CSum<N - 1>::value;
};

int main () {
    // 1+2+・・・9+10の結果を返す
    cout << CSum<10>::value << endl;
    return 0;
}

できました・・・・と!思いきや。このコードはかなり危険です。

「N - 1」のテンプレートを延々とインスタンス化していくので、無限ループに陥ってしまいます。

なのでテンプレートの特殊化を利用し、Nが0のときだけ別のテンプレートを用意します。

#include <iostream>
using std::cout; using std::endl;
 
template<int N>
class CSum {
public:
    static const int value = N + CSum<N - 1>::value;
};

// 0の時だけ特殊化
template<>
class CSum<0> {
public:
    static const int value = 0;
};

int main () {
    // 1+2+・・・9+10の結果を返す
    cout << CSum<10>::value << endl;
    return 0;
}
$ main
55

このように、テンプレートメタプログラミングを利用すると、実行時の負荷を減らすことができるということですね。