テンプレートの部分特殊化 応用編
ロベールの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
ちゃんとうまくいってますね。
あまり有効活用できそうなイメージはしませんが、処理としてはとても面白いですね、部分特殊化。