テンプレート (プログラミング)

出典: フリー百科事典『ウィキペディア(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が出力される

ここで、Tで表されているものをテンプレート仮引数 (template parameter)という。コンパイラは実引数として与えられた値の型(テンプレート実引数template argument。この例の場合では、この整数型リテラルの型であるint)からTに対応する型を導出し、Tに得られたintを当てはめて関数を実体化する。このようにして実体化された関数を特殊化(あるいは特殊化版、特殊バージョン)という。例のmax(3, 7)に対してはこの特殊化が呼ばれることになる。なお、実体化のことを具現化と呼ぶこともある。

この場合xとyがどんな型でも「x < y」という式が生成される。またユーザー定義型の場合も、<演算子が適切に多重定義されていればその型に対してmaxが使える。同様の例は他にもあり、STLには適切な演算子が定義されていれば利用可能になるという関数テンプレートが数多く存在する。例えば<演算子が定義されていれば、sort(), stable_sort(), binary_search()や配列からヒープ構造を作成するアルゴリズム、setなどのコンテナなどが利用可能になる。

逆に標準ライブラリにある複素数を表す型のcomplexには<演算子が定義されていない。複素数には強い順序付けが存在しないからである。そのためmax(x, y)という呼出はxとyが複素数の場合コンパイルエラーになる。このように<演算子を必要とするテンプレートでcomplexを使用することはできない。困ったことにこの種のエラーでは難解なエラーメッセージが出力されてしまう。そのためテンプレートが関わるエラーを出さないよう仕様をよく確認する方が良い。

一般的に、そのようなテンプレート実引数に対する要求は、コンセプト (concept)や要件 (requirement)などとして別途文書によって記述されている。標準C++ライブラリのmax関数テンプレート (X3014 25.3.7)では、そのテンプレート実引数がLessThanComparableでなければならないと定められている。ある型がLessThanComparableであるためには、正にa < bという演算ができなければならない (X3014 20.1.2)と定めれているのである。

クラステンプレートはテンプレートをクラスに当てはめたものである。汎用的なコンテナの作成によく用いられる。たとえばSTLにはリンクリストとしてlistが存在する。整数のリストを作りたければlist<int>と書き、文字列のリストを作りたければlist<string>と書けばよい。

利点と欠点[編集]

テンプレートの用法の中にはプリプロセッサマクロで代替できるものがある。maxもそれにあたり、次のようにmaxマクロを定義できる。

#define max(a, b) ((a) < (b) ? (b) : (a))

マクロでもテンプレートでもコンパイル時までに展開される。マクロは常にインラインに展開されるが、関数テンプレートではコンパイラの判断によってインライン関数として扱われる。そのため(関数テンプレートがインライン展開される限り)実行時のオーバーヘッドは両者共に発生しない。

しかしテンプレートはマクロに比べ型安全であるという点で大きな違いがある。関数形式のマクロでよく起こるエラーをテンプレートでは回避できる。そしてマクロのおそらく重大な欠点として1論理行に収めなければならないということがあり、規模の大きいマクロは書くのが面倒ということがある。

テンプレートには大きく3つの欠点がある。まず歴史的に多くのコンパイラの対応が貧弱だったためテンプレートを使うと移植性が低下する恐れがある。次にどのコンパイラもテンプレートに関するエラーメッセージは訳がわからず役に立たず、テンプレートを使った開発が難しいということがある。最後にテンプレートは実体化される度にコードが生成されていくため、無秩序に使っていくとコードの膨張を引き起こし実行ファイルが大きくなってしまうことがある。

他言語[編集]

C++を基にしたJavaC#では、C++のテンプレートが引き起こした問題を避けるためテンプレートは除外された。しかし、後にテンプレートに似た機能(ジェネリクス・ジェネリック)を導入してジェネリックプログラミングに適応しようとしている。

D言語にもテンプレートは存在するが、C++のものより更に改良を加えられている。

AdaはC++がテンプレートを採用する以前からジェネリクス(汎用体)を持っていたが、それはテンプレートの特殊化が行えないなどC++のテンプレートに比して機能は制限されたものであり、C++のようなテンプレートメタプログラミングを行う事は出来なかった。

参考文献[編集]

  • JIS X 3014:2003 『プログラム言語C++』 [1][2]

関連項目[編集]