オーバーロードされた関数は、一般的に様々なデータ型に対して同様の演算を行う為に使用されます。
MQL4の
ArraSize()関数は簡単な例です。
この関数は任意の型の配列サイズを返します。
実際にはこのシステム関数はオーバーロードされ、このようなオーバーの実装の全体はMQL4アプリケーション開発者から隠されています。
int ArraySize(
void& array[]
);
これはMQL4言語コンパイラはこの関数の呼び出し毎に必要な実装を挿入する事を意味します。
例えば、整数型の配列に対して行う事が出来ます。
int ArraySize(
int& array[]
);
ArraySize()関数は、ヒストリカルデータ形式の引用を使用する為の
MqlRates型の配列の為、以下の通りになります。
int ArraySize(
MqlRates& array[]
);
このように、異なる型の演算の為に同じ関数を使用する事は非常に便利です。
しかし、全ての準備作業(必要な関数は、演算される全てのデータ型に
オーバーロードする必要があります)が行われるべきです。
便利な解決方法があります。
各データ型に対して同様の演算がされるべき時には、関数テンプレートを使用する事が可能です。
この場合、プログラムは関数テンプレートの記述を一つだけにする必要があります。
このようにテンプレートを記述する時、関数が作業する明確なデータ型の代わりに、いくつか仮引数を指定する必要があります。
コンパイラは関数が呼び出される時に使用される引数の型に基づいて、自動的に各型の適切な関数を生成します。
関数テンプレートの定義は、templateキーワードで始まり、角括弧内の仮パラメータリストが続きます。
- 関数の引数の型を指定する
- 関数の戻り値の型を指定する
- 関数定義内で変数を宣言する
テンプレートパラメータの数は8を超える事は出来ません。
テンプレート定義の各仮パラメータは、少なくとも一度は関数パラメータリストに表示されるべきです。
仮パラメータのそれぞれの名前はユニークである必要があります。
任意値の数値型(整数や実数)配列内の最高値を検索する為の関数テンプレートは以下の通りです。
template<typename T>
T ArrayMax(T &arr[]) {
uint size = ArraySize(arr);
if ( size == 0 ) {
return(0);
}
T max = arr[0];
for(uint n=1; n < size; n++) {
if( max < arr[n] ) {
max = arr[n];
}
}
return(max);
}
このテンプレートは渡された配列の最大値を検索する関数を定義し、最大値を返します。
MQL4の
ArryMaximum()関数は最大値のインデックスだけを返す事に注意して下さい、そのインデックスは値を検索する為に使用出来ます。
例えば:
このように、配列の最大値を取得するには2つのステップを実行しました。
ArrayMax()関数テンプレートを使用すると、この関数に適切な型の配列を渡す事で必要な型の結果を得る事が出来ます。
最後の2行の処理の代わりに
関数に渡された配列と同じ型を持っている1行にする事が出来ます。
double max = ArrayMax(array);
この場合、ArrayMax()関数によって返される結果の型は、自動的に配列の型と一致します。
typenameキーワードを使用し、様々なデータ型を演算出来る汎用メソッドを作成する為に、引数の文字列型を取得します。
文字列のデータ型を返す関数の具体例を考えてみます。
#include <Trade\Trade.mqh>
void OnStart() {
CTrade trade;
double d_value = M_PI;
int i_value = INT_MAX;
Print("d_valueの型 = ",GetTypeName(d_value), ", 値 =", d_value);
Print("i_valueの型 = ",GetTypeName(i_value), ", 値 =", i_value);
Print("trade の型 = ",GetTypeName(trade));
}
template<typename T>
string GetTypeName(const T &t) {
return( typename(T) );
}
関数テンプレートはクラスメソッドにも使用する事が出来ます。
class CFile {
public:
template<typename T>
uint WriteStruct(T &data);
};
template<typename T>
uint CFile::WriteStruct(T &data) {
return(FileWriteStruct(m_handle, data));
}
関数テンプレートは
export、
virtual、
#importキーワードで宣言するべきではありません。