This is an old revision of the document!
Nous considérons une fonction index_of
qui effectue la recherche d'un élément dans un tableau. Cette fonction très naïve peut-être écrite comme suit :
int index_of(int* anArray, int theArrayLength, int theValue) { for(int index = 0; index < theArrayLength; index ++) if(anArray[index] == anArray) return index; return -1; }
Cependant, cette fonction ne fonctionne que pour des tableaux d'entiers ayant comme type int
. Si nous envisageons de travailler sur des tableaux de nombres à virgule flottant ayant par exemple le type float
, il faudrait réécrire une nouvelle fonction :
int index_of(float* anArray, int theArrayLength, int theValue) { for(int index = 0; index < theArrayLength; index ++) if(anArray[index] == anArray) return index; return -1; }
dont la seule différence serait que cette fonction prend comme argument un tableau de type float*
et non pas un tableau de type int*
.
Et si nous devons supporter l'ensemble des types correspondant à des nombres entiers et des nombres à virgule flottante, il faudrait réécrire les fonctions pour les types char
, unsigned char
, short
, 'unsigned short,
int,
unsigned int,
long,
unsigned long,
float,
double et enfin
long double. Cela fait beaucoup de code à recopier.
Et si nous envisagions une autre voie, celle de la paramétrisation du type :
<code cpp>
template<class valueT>
int index_of(valueT* anArray, int theArrayLength, valueT theValue)
{
for(int index = 0; index < theArrayLength; index ++)
if(anArray[index] == anArray)
return index;
return -1;
}
</code>
Avec cette nouvelle syntaxe, nous définissons un patron ou un modèle (en anglais template) qui définit une famille de fonctions :
* qui s'appelle
index_of,
* qui prennent trois paramètres :
- un pointeur sur un tableau d'éléments, les éléments ayant chacun pour type
valueT qui est un type paramètre,
- un entier qui donne le nombre d'éléments du tableau,
- un élément de type
valueT qui correspond à l'élément à rechercher dans le tableau.
En fait, quand nous définissons une fonction template, nous ne générons pas de code, nous donnons simplement un modèle au compilateur pour générer une fonction si jamais il est nécessaire de générer une telle fonction.
Supposons désormais que nous effectuons une recherche dans un tableau :
<code cpp>
template<class valueT>
int index_of(valueT* anArray, int theArrayLength, valueT theValue)
{
for(int index = 0; index < theArrayLength; index ++)
if(anArray[index] == anArray)
return index;
return -1;
}
int* arrayOfIntegers = { 1, 3, 4, 2, 9, 5, 7, 8, 6 };
int main()
{
std::cout « “'2' est en position ” « index_of(arrayOfIntegers, 9, 2);
}
</code>
Quand nous écrivons :
<code cpp>
std::cout « “'2' est en position ” « index_of(arrayOfIntegers, 9, 2);
</code>
le compilateur cherche une fonction ayant comme nom
index_of et qui prend comme argument
int*, int
, int
.
index_of(int*, int, int)
.valueT*
, int
, valueT
. De plus, si on remplace valueT
par int
, on génèrera à partir du modèle index_of(valueT*, int, valueT)
la fonction index_of(int*, int, int)
. En conséquence, le compilateur va générer la fonction en remplaçant valueT
par int
et en créant ainsi la fonction index_of(valueT*, int, valueT)
.