Un patron de fonction est introduit avec le mot clé template. Il admet des paramètres "spéciaux" (entre "<" et ">") qui doivent être associés à des arguments connus à la compilation. Notament il accepte des expressions de type (avec typename).
C'est uniquement lors de l'utilisation d'un patron de fonction que du code machine est produit, c'est pourquoi on le place souvent dans un fichier hpp.
template <typename T> int superieur(T a, T b){
if (a > b){
return 1;
}
else{
return 0;
}
}
int c = superieurA<int>(3, 2);
int c = superieurA<double>(3.5, 2);
class A{
int a;
};
A ob1;
A ob2;
//int d = superieurA<A>(ob1,ob2); //erreur
On peut utiliser des argument de type valeur
template <int c> int f(int a){...}
f<3>(5); //ok
int c = ...;
//f<c>(5) // risque d'erreur de compilation
Le compilateur peut déduire les types paramétrés.
template <typename T, typename G> void g(T a,G b){...}
void g(int, int){...} //gii
int main(){
g(3,5.3); //g<int, double>(3,5,3)
g(3,5) //gii
g<int,int>(3, 5) //template
Comme paramètres spécial, on peut utiliser par exemple
typename T& ...typename T* ...typename T (*)(int) ...On peut déclarer une fonction comme const exp2.
Cela autorise le compilateur à l'executer lors de la compilation.
const expr int f(...){...}
template <int c> g(...){...}
g<f(75)>(...); //ok f(75) est calculé lors de la compilation.
On peut également construire et utiliser des patrons de classe.
L'inférence de type est effectuée à partir des appels aux méthodes static (dont font partie les constructeurs). Les "instances" de patrons sont construit lors de la compilation.
template <typename T> class A{
int a = 0;
T b;
public:
void f(){...}
int g(T c);
A (T p) : b{p}{}
};
template <typename T> A<T>::g(T c){...}
int main(){
A<int> obj{3};
obj.f();
A obj{3.5}; // A <double> obj{3.5}
}
On peut utiliser using pour créer des alias de type.
using k = int*;
using G = A<k>;
template <typename A> using ptr = A*;
k c; //int* c;
G u; //A<int*> u;
ptr<int> c; //int*