Funções sobrecarregadas são normalmente usadas para realizar operações similares em vários tipos de dados. ArraySize() é um exemplo simples de tal função em MQL5. Ela retorna o tamanho de qualquer tipo de array. De fato, esta função de sistema é sobrecarregada e a implementação completa de tal sobrecarga é escondida dos desenvolvedores de aplicativos MQL5:



int ArraySize(
void& array[] // array verificado
);


Isso significa que o compilador da linguagem MQL5 insere a implementação necessária para cada chamada desta função. Por exemplo, é assim que é implementado para arrays de tipo inteiro:



int ArraySize(
int& array[] // array com elementos de tipo int
);


A função ArraySize() pode ser exibida da seguinte forma para array de tipo MqlRates para trabalhar com cotações em formato de dados históricos:



int ArraySize(
MqlRates& array[] // array preenchido com valores de tipo MqlRates
);


Assim, é muito conveniente usar a mesma função para trabalhar com tipos diferentes. No entanto, todo trabalho preliminar deve ser realizado - a função necessária deve ser sobrecarregada para todos os tipos de dados com os quais a função deve trabalhar corretamente.

Existe uma solução conveniente. Se operações similares devem ser executadas para cada tipo de dado, é possível usar templates de função. Neste caso, um programador precisa escrever somente uma descrição de template de função. Ao descrever o template de tal forma, nós devemos especificar somente alguns parâmetros formais ao invés de alguns tipos de dados definidos com os quais a função deve trabalhar. O compilador automaticamente gerará várias funções para o apropriado handling de cada tipo baseado nos tipos de argumentos usados ao chamar a função.

A definição de template de função começa com a palavra-chave template seguida pela lista de parâmetros entre chaves angulares. Cada parâmetro formal é precedido pela palavra-chave typename. Tipos de parâmetros formais são tipos incorporados ou definidos pelo usuário. Eles são usados:
•para especificar os tipos de argumentos da função,
•para especificar o tipo de valor de retorno da função,
•para declarar as variáveis dentro da definição da função



O número de parâmetros de template não pode exceder oito. Cada parâmetro formal na definição de template deve aparecer na lista de parâmetros da função pelo menos uma vez. Cada nome de um parâmetro formal deve ser único.

Abaixo está um exemplo de um template de função para buscar do valor mais alto em um array de qualquer tipo numérico (números inteiros ou reais):



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);
}


Este template define a função que encontra o valor mais alto no array passado e retorna este valor como resultado. Lembre-se que a função ArrayMaximum() construída em MQL5 retorna apenas o índice do valor mais alto que pode ser usado para encontrar o valor em si. Por exemplo:



//--- criar array
double array[];
int size=50;
ArrayResize(array,size);
//--- preenche com valores aleatórios
for(int i=0;i<size;i++)
{
array[i]=MathRand();
}

//--- encontra a posição do valor mais alto no array
int max_position=ArrayMaximum(array);
//--- agora, obtém o valor mais alto propriamente no array
double max=array[max_position];
//--- exibe o valor encontrado
Print("Valor max = ",max);


Assim, nós realizamos dois passos para obter obter o valor mais alto no array. Com o template de função ArrayMax(), nós podemos obter o resultado do tipo necessário apenas passando o array de tipo apropriado para esta função. Isso significa que ao invés das últimas duas linhas:



//--- encontra a posição do valor mais alto no array
int max_position=ArrayMaximum(array);
//--- agora, receber o valor mais alto propriamente no array
double max=array[max_position];


nós podemos usar somente uma linha, cujo resultado retornado tem o mesmo tipo que o array passado para a função:



//--- encontra o valor mais alto
double max=ArrayMax(array);


Neste caso, o tipo do resultado retornado pela função ArrayMax() corresponderá automaticamente ao tipo do array.



Use a palavra chave typename para obter o tipo do argumento como uma string a fim de criar métodos de propósito geral para trabalhar com vários tipos de dados. Vamos considerar um exemplo específico da função que retorna tipo de dado como uma string:



#include <Trade\Trade.mqh>
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnStart()
{
//---
CTrade trade;
double d_value=M_PI;
int i_value=INT_MAX;
Print("d_value: tipo=",GetTypeName(d_value), ", valor=", d_value);
Print("i_value: tipo=",GetTypeName(i_value), ", valor=", i_value);
Print("trade: tipo=",GetTypeName(trade));
//---
}
//+------------------------------------------------------------------+
//| Tipo é retornado como uma linha |
//+------------------------------------------------------------------+
template<typename T>
string GetTypeName(const T &t)
{
//--- retorna o tipo como uma linha
return(typename(T));
//---
}




Templates de função podem também serem usados para métodos de classe, por exemplo:



class CFile
{
...
public:
...
template<typename T>
uint WriteStruct(T &data);
};

template<typename T>
uint CFile::WriteStruct(T &data)
{
...
return(FileWriteStruct(m_handle,data));
}


Os templates de função não deve ser declarados com as palavras-chave export, virtual e #import.