テンプレート (プログラミング)
出典: フリー百科事典『ウィキペディア(Wikipedia)』
プログラミングにおけるテンプレートは、データ型にとらわれずにコードを書くことを可能にするC++の機能であり、C++においてはジェネリックプログラミングに用いられる。
C++においてテンプレートは多重継承や演算子多重定義と並ぶ重要な機能となった。STL (Standard Template Library)はテンプレートによって構築されたフレームワークとなっている。
目次 |
[編集] 技術的側面
テンプレートには関数テンプレートとクラステンプレートがある。関数テンプレートは自由な型の引数を受け取ることができる関数のようなものである。たとえば、C++標準ライブラリにある関数テンプレートmax(x, y)はxとyの内、大きな方を返す関数テンプレートで、次のように定義できる。
template <typename T> T max(T x, T y) { if (x < y) return y; else return x; }
そして次のように呼び出せる。
cout << max(3, 7); //7が出力される
コンパイラは引数からmax(int, int)を呼び出すことを決め、Tをintとして実体化する。
この場合xとyがどんな型でも「x < y」という式が生成される。またプログラマが定義した型に対しても<演算子を多重定義してやれば、その型に対してmaxが使える。同様の例は他にもあり、STLには適切な演算子が定義されていれば利用可能になるという関数テンプレートが数多く存在する。例えば<演算子が定義されていれば、sort(), stable_sort(), binary_search()や配列からヒープ構造を作成するアルゴリズム、setなどのコンテナなどが利用可能になる。
逆に標準ライブラリにある複素数を表す型のcomplexには<演算子が定義されていない。複素数には強い順序付けが存在しないからである。そのためmax(x, y)という呼出はxとyが複素数の場合コンパイルエラーになる。このように<演算子を必要とするテンプレートでcomplexを使用することはできない。困ったことにこの種のエラーでは難解なエラーメッセージが出力されてしまう。そのためテンプレートが関わるエラーを出さないよう仕様をよく確認する方が良い。
クラステンプレートはテンプレートをクラスに当てはめたものである。汎用的なコンテナの作成によく用いられる。たとえばSTLにはリンクリストとしてlistが存在する。整数のリストを作りたければlist<int>と書き、文字列のリストを作りたければlist<string>と書けばよい。
[編集] 利点と欠点
テンプレートの用法の中にはプリプロセッサマクロで代替できるものがある。maxもそれにあたり、次のようにmaxマクロを定義できる。
#define max(a, b) ((a) < (b) ? (b) : (a))
マクロでもテンプレートでもコンパイル時までに展開される。マクロは常にインラインに展開されるが、テンプレートではコンパイラの判断によってインライン関数として扱われる。そのため実行時のオーバーヘッドは共にない。
しかしテンプレートはマクロに比べ型安全であるという点で大きな違いがある。関数形式のマクロでよく起こるエラーをテンプレートでは回避できる。そしてマクロのおそらく重大な欠点として1論理行に収めなければならないということがあり、規模の大きいマクロは書くのが面倒ということがある。
テンプレートには大きく3つの欠点がある。まず歴史的に多くのコンパイラの対応が貧弱だったためテンプレートを使うと移植性が低下する恐れがある。次にどのコンパイラもテンプレートに関するエラーメッセージは訳がわからず役に立たず、テンプレートを使った開発が難しいということがある。最後にテンプレートは実体化される度にコードが生成されていくため、無秩序に使っていくとコードの膨張を引き起こし実行ファイルが大きくなってしまうことがある。
[編集] 他言語
C++を基にしたJavaやC#では、C++のテンプレートが引き起こした問題を避けるためテンプレートは除外された。しかし後にテンプレートに似た機能を導入してジェネリックプログラミングに適応しようとしている。
D言語ではC++より更に改良を加えてテンプレートが搭載されている。
Adaにはテンプレートが登場より前からジェネリックスが存在した。
[編集] 関連項目
カテゴリ: プログラミング言語の構文 | C++