関数テンプレートは、引数または戻り値の型だけが異なった、関連する複数の関数を記述したものです。
テンプレートは使用する前に宣言する必要があります。次の例に見られるように、宣言によってテンプレートを使用するのに十分な情報が提供されますが、テンプレートを実装するにはほかの情報も必要です。
template <class Number> Number twice( Number original ); |
この例では Number はテンプレートパラメータであり、テンプレートが記述する関数の範囲を指定します。つまり、Number はテンプレート型のパラメータです。テンプレート定義内で使用すると、型はテンプレートを使用するときに特定されることになります。
テンプレートは宣言と定義の両方が必要になります。テンプレートを定義することで、実装に必要な情報が得られます。次の例は、前述の例で宣言されたテンプレートを定義しています。
template <class Number> Number twice( Number original ) { return original + original; } |
テンプレート定義は通常ヘッダーファイルで行われるので、テンプレート定義が複数のコンパイル単位で繰り返される可能性があります。しかし、すべての定義は同じである必要があります。この制限は「単一定義ルール」と呼ばれています。
コンパイラは、関数パラメータリスト内にテンプレートの型名でないパラメータを含む式をサポートしていません。例を次に示します。
// パラメータリスト内にテンプレートの型名でない // テンプレートパラメータを持つ式はサポートされていません。 template<int I> void foo( mytype<2*I> ) { ... } template<int I, int J> void foo( int a[I+J] ) { ... } |
テンプレートは、いったん宣言するとほかのすべての関数と同様に使用することができます。テンプレートを使用するには、そのテンプレートの名前とテンプレート引数を指定します。コンパイラは、テンプレート型引数を、関数引数の型から推測します。たとえば、以前に宣言されたテンプレートを次のように使用できます。
double twicedouble( double item ) { return twice( item ); } |
テンプレート引数が関数の引数型から推測できない場合、その関数が呼び出される場所にその引数を指定する必要があります。次に例を示します。
template<class T> T func(); // 関数引数なし int k = func<int>(); // テンプレート引数を明示的に指定 |