「テンプレート (プログラミング)」の版間の差分

削除された内容 追加された内容
マークアップ, 内部リンク
2行目:
[[プログラミング (コンピュータ)|プログラミング]]における'''テンプレート'''は、静的型付けの[[C++]]で[[データ型]]にとらわれずにコードを書くことを可能にする機能であり、C++においては[[ジェネリックプログラミング]]に用いられる。
 
C++においてテンプレートは[[多重継承]]や[[多重定義#演算子オーバーロード|演算子多重定義]]と並ぶ重要な機能となった。STL ([[Standard Template Library]])はテンプレートによって構築された[[アプリケーションフレームワーク|フレームワーク]]となっている。
 
== 技術的側面 ==
テンプレートには''[[サブルーチン#関数|関数]]テンプレート''と''[[クラス (コンピュータ)|クラス]]テンプレート''がある。関数テンプレートは自由な型の[[引数]]を受け取ることができる関数のようなものである。たとえば、[[標準C++ライブラリ]]にある関数テンプレート<code>max(x, y)</code><code>x</code><code>y</code>のうち、大きな方を返す関数テンプレートで、次のように定義できる。
<source lang="cpp">
template <typename T>
20行目:
cout << max(3, 7); //7が出力される
</source>
ここで、<code>T</code>で表されているものを''テンプレート[[仮引数]]'' (''template parameter'') という。[[コンパイラ]][[実引数]]として与えられた値の型(''テンプレート実引数''、''template argument''。この例の場合では、この[[整数型]][[リテラル]]の型であるint)<code>int</code>)から<code>T</code>に対応する型を''導出''し、<code>T</code>に得られた<code>int</code>を当てはめて関数を''実体化''する。このようにして実体化された関数を''特殊化''(あるいは特殊化版、特殊バージョン)という。例の<code>max(3, 7)</code>に対してはこの特殊化が呼ばれることになる。なお、実体化のことを''具現化''と呼ぶこともある。
 
この場合<code>x</code><code>y</code>がどんな型でも'''<code>x <&lt; y</code>'''という式が生成される。またユーザー定義型の場合も、<code>&lt;</code>演算子が適切に多重定義されていればその型に対して<code>max</code>が使える。同様の例は他にもあり、STLには適切な演算子が定義されていれば利用可能になるという関数テンプレートが数多く存在する。例えば<code>&lt;</code>演算子が定義されていれば、<code>sort()</code>, <code>stable_sort()</code>, <code>binary_search()</code>や配列から[[ヒープ]]構造を作成するアルゴリズム、<code>set</code>などのコンテナなどが利用可能になる。
 
逆に標準ライブラリにある[[複素数]]を表す型の<code>complex</code>には<code>&lt;</code>演算子が定義されていない。複素数には強い順序付けが存在しないからである。そのため<code>max(x, y)</code>という呼出は<code>x</code><code>y</code>が複素数の場合コンパイルエラーになる。このように<code>&lt;</code>演算子を必要とするテンプレートで<code>complex</code>を使用することはできない。困ったことにこの種のエラーでは難解なエラーメッセージが出力されてしまう。そのためテンプレートが関わるエラーを出さないように、利用する関数テンプレートの仕様をあらかじめよく確認する方が良い。
 
一般的に、そのようなテンプレート実引数に対する要求は、コンセプト (concept) や要件 (requirement) などとして別途文書によって記述されている。標準C++ライブラリの<code>std::max</code>関数テンプレート (X3014 25.3.7) では、そのテンプレート実引数が''LessThanComparable''でなければならないと定められている。ある型がLessThanComparableであるためには、正に<code>a <&lt; b</code>という演算ができなければならない (X3014 20.1.2) と定められているのである。
 
クラステンプレートはテンプレートをクラスに当てはめたものである。汎用的なコンテナの作成によく用いられる。たとえばSTLには[[連結リスト|リンクリスト]]として<code>list</code>が存在する。整数のリストを作りたければlist<code>list&lt;int&gt;</code>と書き、[[文字列]]のリストを作りたければlist<code>list&lt;string&gt;</code>と書けばよい。
 
== 利点と欠点 ==
テンプレートの用法の中には[[プリプロセッサ|プリプロセッサマクロ]]で代替できるものがある。<code>max</code>もそれにあたり、次のように<code>max</code>マクロを定義できる。
<source lang="c">
#define max(a, b) ((a) < (b) ? (b) : (a))
</source>
マクロもテンプレートもコンパイル時までに展開される。マクロは常に[[インライン展開|インラインに展開]]されるが、関数テンプレートではコンパイラの判断によって[[インライン関数]]として扱われる。そのため(関数テンプレートがインライン展開される限り)実行時の[[オーバーヘッド]]は両者共に発生しない。
 
しかしテンプレートはマクロに比べて[[型安全]]であるという点で大きな違いがある。関数形式のマクロでよく起こるエラーをテンプレートでは回避できる。そしてマクロのおそらく重大な欠点として1論理行に収めなければならないということ制限があり、規模の大きいマクロは書くの記述が面倒ということがある。
 
一方、テンプレートには大きく3つの欠点がある。まず歴史的に多くのコンパイラの対応が貧弱だったためテンプレートを使うと移植性が低下する恐れがある。次にどのコンパイラもテンプレートに関するエラーメッセージは訳がわからず役に立たず、テンプレートを使った開発が難しいということがある。最後にテンプレートは実体化される度にコードが生成されていくため、無秩序に使っていくとコードの膨張を引き起こし[[実行ファイル]]が大きくなってしまうこと問題がある。
 
== 他言語 ==