User Tools

Site Tools


cpp:syntax:functions:generic

This is an old revision of the document!


Les fonctions génériques en C++

Pourquoi rendre des fonctions paramétrables par des types ?

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.

Les fonctions paramétrables ?

C++ propose de définir des fonctions paramétrables par le type des arguments. Ainsi la fonction précédente peut-être paramétrer par le type des éléments stockés dans le tableau comme suit :

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

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'appellent index_of,
  • qui prennent trois paramètres :
    1. un pointeur sur un tableau d'éléments, les éléments ayant chacun pour type valueT qui est un type paramètre,
    2. un entier qui donne le nombre d'éléments du tableau,
    3. 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 :

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

Quand nous écrivons :

    std::cout << "'2' est en position " << index_of(arrayOfIntegers, 9, 2);

le compilateur cherche une fonction ayant comme nom index_of et qui prend comme argument int*, int, int.

  • Il n'existe pas de fonction index_of(int*, int, int).
  • Il existe une fonction template, donc un modèle de fonction qui prend trois arguments : valueT*, int, valueT.
    Si on remplace valueT par int, on génèrera à partir du modèle index_of(valueT*, int, valueT) une fonction index_of(int*, int, int).
    Le compilateur génère la fonction index_of(int*, int, int) en remplaçant valueT par int et en créant ainsi la fonction index_of(valueT*, int, valueT).

Pour aller plus loin

cpp/syntax/functions/generic.1617713345.txt.gz · Last modified: 2021/04/06 12:49 by bmonsuez