テンプレート (プログラミング)
C++のテンプレートは完全にコンパイル時点でタイプセーフである。例えば、複素数には狭義の順序 (strict order) がないので、標準C++ライブラリの複素数型であるcomplexには<演算子が定義されていない。従って、前述のmax関数テンプレートにcomplex型を指定した場合、コンパイルエラーとなる。同様に、<をあてにする他のテンプレートはcomplexデータに適用できない。ただ、通例コンパイラはこの種のエラーに対して、難解でほとんど役に立たないエラーメッセージを出力する。テンプレートが関わるエラーを出さないように、プログラマーは利用する関数テンプレートの仕様をあらかじめよく確認しておくしかない。
一般的に、そのようなテンプレート実引数に対する要求は、コンセプト (concept) や要件 (requirement) などとして別途文書によって記述されている。標準C++ライブラリのstd::max関数テンプレート (X3014 25.3.7) では、そのテンプレート実引数がLessThanComparableでなければならないと定められている。ある型がLessThanComparableであるためには、正にa < bという演算ができなければならない (X3014 20.1.2) と定められているのである。
テンプレートの用法の中にはC言語のプリプロセッサマクロで代替できるものがある。例えばmax関数テンプレートの代替として、次のようにMAXマクロを定義できる。
マクロもテンプレートもコンパイル時までに展開される。マクロは常にインライン展開されるが、関数テンプレートはコンパイラの判断によってインライン関数として扱われる。そのため(関数テンプレートがインライン展開される限り)実行時のオーバーヘッドは両者共に発生しない。
しかしテンプレートはマクロに比べて型安全であるという点で大きな違いがある。関数形式のマクロでよく起こるエラーをテンプレートでは回避できる。関数テンプレートでは、関数形式マクロのように引数の意図しない多重評価は起こらない。そしてマクロのおそらく重大な欠点として1論理行に収めなければならないという制限があり、規模の大きいマクロは記述が面倒ということがある。テンプレートはマクロよりも大規模なコードに対して特に効果的である。また、マクロは常にグローバル名前空間を汚染するが、テンプレートは任意の名前空間あるいは構造体やクラスの内部に定義することができる。
一方、テンプレートには大きく三つの欠点がある。それはコンパイラのサポート、貧弱なエラーメッセージ、コードの肥大化である。
まず、歴史的に多くのコンパイラの対応が貧弱だったため、テンプレートを使うと移植性が低下する恐れがある。C++について考慮していないリンカを利用するとき、あるいは共有ライブラリの境界を越えてテンプレートを使おうとしたときも十分な対応がなされていない処理系があった。C++98以降はテンプレートを含めた規格標準化とコンパイラ対応が進み、改善されている。
テンプレートの明示的特殊化 (explicit specialization) は、テンプレート引数について、特定の型に対する明示的個別実装を可能とする機能である。テンプレートの明示的特殊化は、特定の形式に最適化できるようにすることと、コード肥大化の削減に役立てることという2つの目的がある。
例としてsort()関数テンプレートについて考える。このような関数の動作は第一にコンテナの特定位置の2つの値を入れ替えまたは交換することである。値が多い場合(各要素を格納するためにメモリを消費するという点で)、オブジェクトへのポインタのリストを先に構築し、それらのポインタをソートして、最終的なソートされたシーケンスを構築するのが多くの場合で高速である。値が非常に少なければ単純に必要に応じて値をスワップで置き換えるのが最も速い。しかしさらにパラメータ化された型がポインタ型である場合はポインタの配列を構築する必要がない。テンプレートの明示的特殊化はテンプレートの実装者が複数の異なる実装を記述することを可能にし、パラメータ化された型が各実装で利用されるべき特徴を指定できるようにする。
テンプレートの部分特殊化 (partial specialization) は、テンプレート仮引数の一部を特殊化するものである。明示的特殊化と異なる点は、特殊化されず抽象化されたままのテンプレート仮引数を持つことである。