テンプレートの部分特殊化 応用編

ロベールのC++入門講座 13-13

テンプレートの部分特殊化については以前テンプレートの部分特殊化 - (void*)Pないとにて勉強しました。

このときやった実装例は、ある型とその型のポインタで部分特殊化するというものでしたが、それ以外にも複雑な部分特殊化もできるのです。

まずテンプレート引数が二つあった場合の処理を考えてみます。

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

template<class T, class U>
class CSample {
public:
    CSample(T t,U u){
        m_t = t;
        m_u = u;
    } 
    void Output() {
        cout << m_t << "+" << m_u << endl;
    }
private:
    T m_t;
    U m_u;
};

int main () {
    CSample<char*,int> obj("abc",20);
    
    obj.Output();
}
$ main
abc+20

与えられた二つの引数を"+"という文字列で連結して表示するだけの処理です。

さてこれを、部分特殊化してみます。

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

template<class T, class U>
class CSample {
public:
    CSample(T t,U u){
        m_t = t;
        m_u = u;
    } 
    void Output() {
        cout << m_t << "+" << m_u << endl;
    }
private:
    T m_t;
    U m_u;
};

// テンプレート第一引数がintの場合だけ部分特殊化する
template<class U>
class CSample<int,U> {
public:
    CSample(int t,U u){
        m_t = t;
        m_u = u;
    } 
    void Output() {
        // 100を足した結果を表示させる
        cout << (m_t+100) << "+" << m_u << endl;
    }
private:
    int m_t;
    U m_u;
};



int main () {
    CSample<char*,int> obj1("abc",20); // 通常のテンプレート
    CSample<int,char*> obj2(20,"abc"); // 部分特殊化されたテンプレート
    
    obj1.Output();
    obj2.Output();
}
$ main
abc+20
120+abc

できました。

// テンプレート第一引数がintの場合だけ部分特殊化する
template<class U>
class CSample<int,U> {

と、あるようにテンプレートの第一引数がintの場合だけ部分特殊化する処理になります。

次に同じ型がテンプレート引数に指定された場合に部分特殊化する処理を書いてみます。

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

template<class T, class U>
class CSample {
public:
    CSample(T t,U u){
        m_t = t;
        m_u = u;
    } 
    void Output() {
        cout << m_t << "+" << m_u << endl;
    }
private:
    T m_t;
    U m_u;
};


// 同じ型が指定された場合の部分特殊化
template<class T>
class CSample<T,T> {
public:
    CSample(T t,T u){
        m_t = t;
        m_u = u;
    } 
    void Output() {
        // "="で連結して表示する
        cout << m_t << "=" << m_u << endl;
    }
private:
    T m_t;
    T m_u;
};


int main () {
    CSample<char*,int> obj1("abc",20); // 通常のテンプレート
    CSample<int,int>   obj2(100,2000); // 部分特殊化されたテンプレート
    
    obj1.Output();
    obj2.Output();
}
$ main
abc+20
100=2000

ちゃんとうまくいってますね。

あまり有効活用できそうなイメージはしませんが、処理としてはとても面白いですね、部分特殊化。