文法:
template <class データ型> 返値の型 名前( パラメータリスト ) { 命令リスト; }
テンプレートは汎用の関数やクラスを作成するのに使用されます。汎用の関数やクラスは、指定されたデータ型の詳細を使用時まで知らせなくても、操作するコードを書くことができます。”データ型”というプレースホルダーが他の多くのデータ型と置換されることで、この機能は実現されています。
例えば、以下のコードは汎用的な変数の入れ替え関数を定義しています。置き換える2つの変数にはあらゆる型を指定することができます:
template<class X> void genericSwap( X &a, X &b ) { X tmp; tmp = a; a = b; b = tmp; } int main(void) { ... int num1 = 5; int num2 = 21; cout << "入れ替え前: num1 = " << num1 << ", num2 = " << num2 << endl; genericSwap( num1, num2 ); cout << "入れ替え後: num1 = " << num1 << ", num2 = " << num2 << endl; char c1 = 'a'; char c2 = 'z'; cout << "入れ替え前: c1 = " << c1 << ", c2 = " << c2 << endl; genericSwap( c1, c2 ); cout << "入れ替え後: c1 = " << c1 << ", c2 = " << c2 << endl; ... return( 0 ); }
次のテンプレートは、汎用クラスを宣言しています。
#include <cassert> const unsigned int maxSize = 20; template<class T> class simpleStack { public: simpleStack(): amount(0) {} bool empty() const { return amount == 0; } bool full() const { return amount == maxSize; } unsigned int size() const { return amount; } void clear() { amount = 0; } const T& top() const; void pop(); void push( const T &x); private: unsigned int amount; T array[ maxSize ]; }; template<class T> const T& simpleStack<T>::top() const { assert( !empty() ); return array[ amount - 1 ]; } template<typename T> /*宣言のclassはtypenameと置き換えても同じ意味を持ちます*/ void simpleStack<T>::pop() { assert( !empty() ); --amount; } template<typename T> void simpleStack<T>::push(const T &x) { assert( !full() ); array[ amount++ ] = x; } #include <iostream> /* main code */ int main() { simpleStack< int > aIntStack; int i = 100; while ( !aIntStack.full() ) aIntStack.push( i++ ); cout << "スタックサイズ: " << aIntStack.size() << endl; return 0; }
templateキーワードは、テンプレートを参照している依存名を表すのにも使用されます。typenameキーワードとは異なり、templateキーワードはテンプレートのメンバー名の直前に置かれます。サンプル:
struct Foo { template<typename T> struct Member { typedef int type; }; }; template<class T> struct Bar { typedef typename T::template Member<int>::type bar; }; typedef Bar<Foo> FooBar;
関連トピック: typename