C++学習のテンプレート特例化
テンプレートはC++の重要な特性であり、ユーザー定義タイプを含む複数のデータ型にコードを書くことができます.たとえば、STLのsort()関数は、複数のデータ型のソートに使用でき、クラスstackは複数のデータ型のスタックとして使用できます.しかし、汎用テンプレートではなく、特定のデータ型に対して異なるコードを実行したい場合は、テンプレート特例化(template specialization)を使用します.
一、関数テンプレートの特例化
関数テンプレートを特例化する場合は、元のテンプレートの各テンプレートパラメータに実パラメータを指定する必要があります.キーワードtemplateの後に空のカッコ<>、すなわち
出力結果:
int型を除く他のデータ型については、汎用バージョンの関数テンプレート
二、クラステンプレートの特例化
特例化関数テンプレートに加えて、クラステンプレートを特例化することもできます.簡単な例を次に示します.
偏特化または
一部特例化(partial specialization).たとえば、C++標準ライブラリのクラスvectorの定義:
1つのパラメータはboolタイプにバインドされますが、もう1つのパラメータはバインドされていません.ユーザーが指定する必要があります.クラステンプレートの一部の特例化バージョンは依然として1つであることに注意してください.
ユーザーは、特例化されたバージョンで指定されていないテンプレートパラメータにも実パラメータを指定する必要があるため、テンプレートを使用します.
一、関数テンプレートの特例化
関数テンプレートを特例化する場合は、元のテンプレートの各テンプレートパラメータに実パラメータを指定する必要があります.キーワードtemplateの後に空のカッコ<>、すなわち
template <>
を使用して、テンプレートを特例化していることを示します.template <typename T>
void fun(T a)
{
cout << "The main template fun(): " << a << endl;
}
template <> // int
void fun(int a)
{
cout << "Specialized template for int type: " << a << endl;
}
int main()
{
fun<char>('a');
fun<int>(10);
fun<float>(9.15);
return 0;
}
出力結果:
The main template fun(): a
Specialized template for int type: 10
The main template fun(): 9.15
int型を除く他のデータ型については、汎用バージョンの関数テンプレート
fun(T a)
が呼び出される.int型の場合、特例化バージョンのfun(int a)
が呼び出されます.特例化されたバージョンの本質は、関数のリロードではなくインスタンスであることに注意してください.したがって,特例化は関数マッチングに影響しない.二、クラステンプレートの特例化
特例化関数テンプレートに加えて、クラステンプレートを特例化することもできます.簡単な例を次に示します.
template <typename T>
class Test{
public:
void print(){
cout << "General template object" << endl;
}
};
template<> // int
class Test<int>{
public:
void print(){
cout << "Specialized template object" << endl;
}
};
int main()
{
Test<int> a;
Test<char> b;
Test<float> c;
a.print();
b.print();
c.print();
return 0;
}
出力結果:Specialized template object
General template object
General template object
さらに、クラステンプレートの特例化は、関数テンプレートとは異なり、すべてのテンプレートパラメータに実パラメータを提供する必要はない.クラステンプレートと呼ばれるすべてのテンプレートパラメータではなく、一部のみを指定できます.偏特化または
一部特例化(partial specialization).たとえば、C++標準ライブラリのクラスvectorの定義:
template <typename T, typename Allocator>
class vector
{
/*......*/
};
//
template <typename Allocator>
class vector<bool, Allocator>
{
/*......*/
};
vectorの例では、1つのパラメータはboolタイプにバインドされますが、もう1つのパラメータはバインドされていません.ユーザーが指定する必要があります.クラステンプレートの一部の特例化バージョンは依然として1つであることに注意してください.
ユーザーは、特例化されたバージョンで指定されていないテンプレートパラメータにも実パラメータを指定する必要があるため、テンプレートを使用します.