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

削除された内容 追加された内容
ジェネリックプログラミング (oldid=72181120) から記述を移植。
編集の要約なし
29行目:
cout << max(-3.1, -8) << endl; // double, int の曖昧さが解決できないためコンパイルエラー。
</source>
ここで、テンプレート内にて<code>T</code>で表されているものを'''テンプレート[[仮引数]]''' (''template parameter'') という。<code>T</code>はパラメータ化された型 (parameterized type) とも呼ばれる。テンプレート仮引数の列挙には<code>typename</code>キーワードもしくは<code>class</code>キーワードを用いて修飾する必要がある。テンプレート自身は実体をもたないため、利用する際は'''実体化''' (instantiate) する必要がある。実体化の方法のひとつとして、<code>max&lt;int&gt;</code>のように具体的な型すなわち'''テンプレート[[実引数]]''' (''template argument'') を明示的に指定することができるが、曖昧さがない場合に限り、[[コンパイラ]]は関数テンプレートの[[実引数]]として与えられた値の型(この例の場合では、<code>x</code>および<code>y</code>として渡された[[整数型]][[リテラル]]の型である<code>int</code>)から<code>T</code>に対応する型を'''推論'''し、得られた具体的な型<code>int</code>を<code>T</code>に当てはめて関数を暗黙的に実体化することもできる。このようにして実体化された関数を'''特殊化'''(あるいは特殊化版、特殊バージョン)という。例の<code>max&lt;int&gt;(3, 7)</code>, <code>max(3, 7)</code>に対しては<code>int</code>の特殊化が、<code>max&lt;double&gt;(-3.1, -8)</code>, <code>max(-3.1, -8.0)</code>に対しては<code>double</code>の特殊化が呼ばれることになる。なお、実体化のことを'''具現化'''と呼ぶこともある。
 
<code>max</code>のインスタンス化に際して、<code>x</code>と<code>y</code>がどんな型でも'''<code>x &lt; y</code>'''という式が生成される。またユーザー定義型の場合も、<code>&lt;</code>演算子が適切に多重定義されていればその型に対して<code>max</code>が使える。<code>T</code>として利用可能な型の集合に何らかの共通の[[継承 (プログラミング)|継承]]関係がある必要はない。つまり、テンプレートは静的な[[ダック・タイピング]] (duck typing) を可能とする。同様の例は他にもあり、STLには適切な演算子が定義されていれば任意の型が利用可能になるという関数テンプレートが数多く存在する。例えば<code>&lt;</code>演算子が定義されていれば、<code>sort()</code>, <code>stable_sort()</code>, <code>binary_search()</code>や、配列から[[ヒープ]]構造を作成するアルゴリズム{{要説明|date=2019-03}}、<code>set</code>などのコンテナなどが利用可能になる。関数テンプレートには述語 (predicate) として[[関数オブジェクト]]を受け取るものも存在し、ソートの比較などに使われる[[コールバック関数]]をカスタマイズすることが容易になっている。つまり、要件を満たすためのいくつかの演算子を定義するだけで、新しいデータ型に対して幅広い機能を得られる。
39行目:
テンプレートに関するコンパイルエラーメッセージを改善するために、[[C++0x]]では[[コンセプト (C++)|コンセプト]]と呼ばれる機能の導入が検討されていたが、結局[[C++11]]では見送られた。コンセプトは[[C++17]]規格でも実装されていない。
 
クラステンプレートはテンプレートの概念をクラスに当てはめたものである。汎用的なコンテナ (generic containers) の作成によく用いられる。たとえばSTLには[[連結リスト|リンクリスト]]として<code>std::list</code>が存在する。整数のリストを作りたければ<code><nowiki>std::list<int></nowiki></code>と書き、[[文字列]]のリストを作りたければ<code><nowiki>std::list<std::string></nowiki></code>と書けばよい。<code>std::list</code>の要素型に対する要件は規格バージョンによって異なるが、例えばC++03までは''CopyAssignable''および''CopyConstructible''を必要とする<ref>[https://ja.cppreference.com/w/cpp/container/list std::list - cppreference.com]</ref>。これらの要件を満たす限り、たとえどんな型が<code>std::list</code>の要素型として指定されても動作する共通の関数集合が定義されている。なお、関数テンプレートと違い、クラステンプレートではテンプレート引数を[[型推論]]することができなかったが、[[C++17]]にてサポートされるようになった。
 
テンプレート引数の数はC++03までは固定であり、定義時にひとつひとつ明示的に指定する必要があったが、[[C++11]]では可変引数テンプレート (variadic template) がサポートされるようになった。[[可変長引数]]の関数やマクロのように、<code>...</code>という記法を用いて記述する。