Rechercher
 

Améliorations / Corrections

Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.

Emplacement :

Description des améliorations :

Spécialisation de templates

La spécialisation de template permet de définir plusieurs templates de même nom en garantissant que ce sera toujours le plus spécifique qui sera utilisé pour produire vos fonctions, classes et méthodes. En effet, et théoriquement, un template peut être utilisé pour une infinité de type de données : il envisageable que dans certains cas, ce template ne soit pas le plus approprié. Il est alors possible de définir un template spécialisé pour certains de ces types.

Exemple de mise en oeuvre d'une spécialisation de template

Dans l'exemple ci-dessous, un template nommé Pair est défini et accepte deux paramètres génériques (T1 et T2). Normalement, ce template pourrait être instancié pour n'importe quel couple de types de données : s'il est utilisé, son constructeur devrait afficher "Master template". Sauf qu'une spécialisation est définie si le second type générique est fixé sur int : dans ce cas, le constructeur produit devrait afficher "Specialized template 1". De même, une seconde spécialisation est définie si le premier type générique est fixé sur double : cas ce cas, l'affichage sera "Specialized template 2".

La fonction main utilise ensuite ces templates en prenant soin de bien tester les trois alternatives.

Notez que la dernière ligne du main, avant le return, ne compile pas (c'est pour cela qu'elle est commentée). Effectivement, si le premier type générique est fixé à double et que le second est fixé à int, alors le compilateur pourrait appliquer ces deux spécialisations de même priorité : du coup et dans de tel cas, il préférera s'abstenir de choisir et donc produire une erreur de compilation.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
#include <iostream>

using namespace std;

template <typename T1, typename T2>
class Pair {
    T1 first;
    T2 second;
public:
    Pair( const T1 & t1, const T2 & t2 ) {
        this->first = t1;
        this->second = t2;
        cout << "Master template" << endl;
    }
};

template <typename T>
class Pair<T, int> {
    T first;
    int second;
public:
    Pair( const T & t1, int i ) {
        this->first = t1;
        this->second = i;
        cout << "Specialized template 1" << endl;
    }
};

template <typename T>
class Pair<double, T> {
    double first;
    T second;
public:
    Pair( double d, const T & t2 ) {
        this->first = d;
        this->second = t2;
        cout << "Specialized template 2" << endl;
    }
};


int main( int argc, char * argv[] ) {

    Pair<const char *, const char *> p1( "toto", "titi" );
    Pair<const char *, int> p2( "toto", 2 );
    Pair<double, const char *> p3( 3.141592654, "toto" );
    //Pair<double, int> p4( 3.141592654, 4 );    // Does not compile: ambiguous declarations

    return 0;
}
Exemple de spécialisations d'un template

Notez que la dernière ligne du main, avant le return, ne compile pas (c'est pour cela qu'elle est commentée). Effectivement, si le premier type générique est fixé à double et que le second est fixé à int, alors le compilateur pourrait appliquer ces deux spécialisations de même priorité : du coup et dans de tel cas, il préférera s'abstenir de choisir et donc produire une erreur de compilation. A titre d'information, voici le message d'erreur que produirait le compilateur g++ dans ce cas.

[~/Desktop]$ g++ -o Sample Sample.c
Sample.c: In function 'int main(int, char**)':
Sample.c:46:25: error: ambiguous class template instantiation for 'class Pair<double, int>'
     Pair<double, int> p4( 3.141592654, 4 );    // Does not compile: ambiguous declarations
                         ^
Sample.c:18:7: error: candidates are: class Pair<T, int>
 class Pair<T, int> {
       ^
Sample.c:30:7: error:                 class Pair<double, T>
 class Pair<double, T> {
       ^
Sample.c:46:25: error: variable 'Pair<double, int> p4' has initializer but incomplete type
     Pair<double, int> p4( 3.141592654, 4 );    // Does not compile: ambiguous declarations
                         ^
[~/Desktop]$

Spécialisation totale d'un template

Si vous souhaitez régler cette erreur de compilation, une solution pourra être de totalement spécialiser le template pour les deux types double et int. Voici un exemple de spécialisation totale.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 
 61 
 62 
#include <iostream>

using namespace std;

template <typename T1, typename T2>
class Pair {
    T1 first;
    T2 second;
public:
    Pair( const T1 & t1, const T2 & t2 ) {
        this->first = t1;
        this->second = t2;
        cout << "Master template" << endl;
    }
};

template <typename T>
class Pair<T, int> {
    T first;
    int second;
public:
    Pair( const T & t1, int i ) {
        this->first = t1;
        this->second = i;
        cout << "Specialized template 1" << endl;
    }
};

template <typename T>
class Pair<double, T> {
    double first;
    T second;
public:
    Pair( double d, const T & t2 ) {
        this->first = d;
        this->second = t2;
        cout << "Specialized template 2" << endl;
    }
};

template <>
class Pair<double, int> {
    double first;
    int second;
public:
    Pair( double d, int i ) {
        this->first = d;
        this->second = i;
        cout << "Fully specialized template" << endl;
    }
};


int main( int argc, char * argv[] ) {

    Pair<const char *, const char *> p1( "toto", "titi" );
    Pair<const char *, int> p2( "toto", 2 );
    Pair<double, const char *> p3( 3.141592654, "toto" );
    Pair<double, int> p4( 3.141592654, 4 );
    
    return 0;
}
Spécialisation totale du template

Voici les résultats produits par l'execution de notre exemple de spécialisation totale du template.

[~/Desktop]$ g++ -o Sample Sample.c
$> Essai
Master template
Specialized template 1
Specialized template 2
Fully specialized template
$>