テンプレート関数
C++では関数を定義する際、引数には指定した型しか渡すことができません。
例えば引数をint型に指定した関数にdouble型の変数を渡すことはできません。
これは関数のオーバーロードを使うことで解決することができます。
オーバーロードによって引数の異なる同名関数を定義することが出来ます。
詳しくはデフォルト引数と関数のオーバーロードを参照。
しかし、オーバーロードをする場合、想定される引数の型の種類ごとに定義を記述しなければなりません。
引数の数が異なる場合はそれぞれ処理がことなりますが、引数の型のみが違う場合、処理内容が同じときがありますね。
にも関わらず同一のソースコードをコピーするのは無駄な作業です。
この問題を解決するのがテンプレート関数です。
テンプレート関数は型によって差異の無い処理を1度の記述で済ませる機能です。
テンプレート関数を定義するには以下のように記述します。
template <typename 【型名】> 【戻り値の型】 【関数名】(【引数】)
{
【処理】
}
型名には一般化した時に置き換える型の名前を設定します。
慣習的にはTとすることが多いです。
その他の項目は通常の関数と同じですが、戻り値と引数にはtypenameで指定した型名を使うことが出来ます。
例えば以下のようになります。
template <typename T> T f(T t)
{
【処理】
}
この場合、関数の呼び出し時にint型を指定するとTがintに置き換わります。
すなわち以下のような関数を呼び出したことになります。
int f(int t)
char型でもfloat型でも同様です。
char f(char t)
float f(float t)
テンプレート関数では複数の型を用いることができます。
<>内にtypenameを「,」で区切って複数並べます。
こうすることで複数の引数それぞれに別の型を指定できます。
関数の定義内ではここで指定した引数tを使うことができます。
しかし、そこではどんな型でも行える処理しか記述することはできません。
特にテンプレートでない関数を呼び出す時は注意しましょう。
また、テンプレート関数自体がオーバーロードに近い性質を持ちますが、テンプレート関数をオーバーロードすることも可能です。
この場合、型の種類は変わらず引数の数を換えることができます。
テンプレートクラス
テンプレート機能をクラスに適用することも可能です。
テンプレート機能を使用したクラスをテンプレートクラスと呼びます。
定義は以下のようになります。
template <typename 【型名】> class 【クラス名】
{
【クラスの定義】
}
クラス内で定義するメンバ変数・メンバ関数にここで設定した型名(T)が使えます。
メンバ関数をテンプレート化する際に上記のテンプレート関数で定義することも可能ですが、メンバ関数の場合メンバ変数にアクセスすることが多い為クラスをテンプレートにしなければならない場合が多いでしょう。
インスタンスを生成するには以下のようになります。
【クラス名】<【型名】> 【インタンス名】
インスタンス生成時に型名が置き換わります。
同一インスタンス内でテンプレートを用意する場合はテンプレート関数を使用しなければなりません。
typeid演算子
テンプレート関数、クラスがどの型になっているのか確認する方法があります。
typeid演算子を使います。
typeid(【型】).name()
型には今、何の型になっているのか知りたい型名(T)が入ります。
typeidを使うには<typeinfo>をインクルードする必要があります。
#include <typeinfo>