OVH Cloud OVH Cloud

Templates en C++

6 réponses
Avatar
Hugues Delorme
Voilà le problème :

Soit la classe générique :
template<class G, class H>
class GClass;

Je voudrais en définir une version générique avec un seul paramètre
formel(le 2° paramètre formel H est fixe : GClass<G, int> par exemple).
Est-il possible de conserver le même nom de classe, c'est-à-dire GClass<G> ?

J'avais pensé à la solution triviale :
template<class G>
class DefGClass : public GClass<G, int>
{
//etc.
};

Mais on est obligé d'utiliser un nom différent.

---
Hugues DELORME
Techni-Modul
Ingénieur Logiciel
20 rue Georges Besse, ZI du Brézet
63100 Clermont-Ferrand

6 réponses

Avatar
Benoit Rousseau
Hugues Delorme wrote:
Voilà le problème :

Soit la classe générique :
template<class G, class H>
class GClass;

Je voudrais en définir une version générique avec un seul paramètre
formel(le 2° paramètre formel H est fixe : GClass<G, int> par exemple).
Est-il possible de conserver le même nom de classe, c'est-à-dire GClass<G> ?

J'avais pensé à la solution triviale :
template<class G>
class DefGClass : public GClass<G, int>
{
//etc.
};

Mais on est obligé d'utiliser un nom différent.



Andrei Alexandrescu (Modern C++ Design) décrit ca comme la
spécialisation de template :

template <class G, class H>
class GClass {
//generic implementation
};

template < >
class GClass<double, int> {
//specialized implementation
};

int main() {
GClass< int, double > gc2;
GClass<> gc0;
}

Mais ce code ne marche pas chez moi (g++ 3.2.2) :
specialize.cc: In function `int main()':
specialize.cc:19: wrong number of template arguments (0, should be 2)
specialize.cc:6: provided for `template<class G, class H> class GClass'
specialize.cc:19: ISO C++ forbids declaration of `gc0' with no type

Est ce que quelqu'un sait pq ?


--
--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/

Avatar
Christophe Lephay
Benoit Rousseau wrote:
Hugues Delorme wrote:
Voilà le problème :

Soit la classe générique :
template<class G, class H>
class GClass;

Je voudrais en définir une version générique avec un seul paramètre
formel(le 2° paramètre formel H est fixe : GClass<G, int> par
exemple). Est-il possible de conserver le même nom de classe,
c'est-à-dire GClass<G> ?

J'avais pensé à la solution triviale :
template<class G>
class DefGClass : public GClass<G, int>
{
//etc.
};

Mais on est obligé d'utiliser un nom différent.



Andrei Alexandrescu (Modern C++ Design) décrit ca comme la
spécialisation de template :

template <class G, class H>
class GClass {
//generic implementation
};

template < >
class GClass<double, int> {
//specialized implementation
};

int main() {
GClass< int, double > gc2;
GClass<> gc0;
}

Mais ce code ne marche pas chez moi (g++ 3.2.2) :


Il me semble que la spécialisation de templates ne marche que pour les
fonctions (car on peut surcharger des fonctions, mais pas des classes)...

Chris


Avatar
Benoit Rousseau
Christophe Lephay wrote:


Il me semble que la spécialisation de templates ne marche que pour les
fonctions (car on peut surcharger des fonctions, mais pas des classes)...

Chris


Le livre d'Alexandrescu dit exactement le contraire...
Ce qu'il y a plus haut dans le thread est 'juste' d'après lui, et :

template <class T, class U> T Fun(U obj); //primary template
template <class U> void Fun<void, U>(U obj); //illegal partial
// specialization
template <class T> T Fun( Window obj ); //legal (overloading)

Mais une bonne partie du bouquin est basée sur la spécialisation des
classes... Ce serait dommage qu'il ait tord.


--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/

Avatar
Bertrand Motuelle
Benoit Rousseau wrote:
Christophe Lephay wrote:
Il me semble que la spécialisation de templates ne marche que pour les
fonctions (car on peut surcharger des fonctions, mais pas des classes)...

Le livre d'Alexandrescu dit exactement le contraire...

Ce qu'il y a plus haut dans le thread est 'juste' d'après lui, et :

template <class T, class U> T Fun(U obj); //primary template
template <class U> void Fun<void, U>(U obj); //illegal partial
// specialization
template <class T> T Fun( Window obj ); //legal (overloading)

Mais une bonne partie du bouquin est basée sur la spécialisation des
classes... Ce serait dommage qu'il ait tord.


La specialisation explicite (tous les parametres d'un template sont
fixe's) marche pour les classes et pour les fonctions.
La specialisation partielle (une partie des parametres du template sont
fixes) ne marche que pour les classes.

Dans l'exemple que tu avais poste Benoit, le probleme est que la seconde
declaration doit indiquer les parametres templates:

template <class G, class H>
class GClass {};

template <>
class GClass<double, int> { }; // specialisation explicite

int main()
{
GClass< int, double > gc2;
GClass<double, int> gc0; // ici manquaient les parametres du template
}


On peut aussi declarer une specialisation partielle du template comme ceci:

template<class G>
class GClass<G, int> {}; // Ne marche que pour les classes.

Bertrand.


Avatar
Loïc Joly
Benoit Rousseau wrote:

Hugues Delorme wrote:

Voilà le problème :

Soit la classe générique :
template<class G, class H>
class GClass;

Je voudrais en définir une version générique avec un seul paramètre
formel(le 2° paramètre formel H est fixe : GClass<G, int> par exemple).
Est-il possible de conserver le même nom de classe, c'est-à-dire
GClass<G> ?

J'avais pensé à la solution triviale :
template<class G>
class DefGClass : public GClass<G, int>
{
//etc.
};

Mais on est obligé d'utiliser un nom différent.



Andrei Alexandrescu (Modern C++ Design) décrit ca comme la
spécialisation de template :


Je crois que le problème est différent. Je n'ai pas encore déterminé
s'il s'agissait des typedef template, (qui lui n'a pas (encore) de
bonne solution en C++), ou des arguments par défaut de template.


template <class G, class H>
class GClass {
//generic implementation
};

template < >
class GClass<double, int> {
//specialized implementation
};

int main() {
GClass< int, double > gc2;
GClass<> gc0;
}

Mais ce code ne marche pas chez moi (g++ 3.2.2) :
specialize.cc: In function `int main()':
specialize.cc:19: wrong number of template arguments (0, should be 2)
specialize.cc:6: provided for `template<class G, class H> class GClass'
specialize.cc:19: ISO C++ forbids declaration of `gc0' with no type

Est ce que quelqu'un sait pq ?


Là, tu as défini une spécialisation. Ca veut juste dire qui si un
utilisateur écrit GClass< double, int>, il va se retouver avec une
définition de classe différente de celle qu'il aurait pour d'autres types.

Il y a aussi la spécialisation partielle (ne marche pas avec certains
compilos encore répandus) qui permet de dire, par exemple, que tous les
templates GClass dont le premier argument template est un string seront
définis différemment de l'implémentation classique.

--
Loïc


Avatar
Bertrand Motuelle
Hugues Delorme wrote:
Voilà le problème :

Soit la classe générique :
template<class G, class H>
class GClass;

Je voudrais en définir une version générique avec un seul paramètre
formel(le 2° paramètre formel H est fixe : GClass<G, int> par exemple).
Est-il possible de conserver le même nom de classe, c'est-à-dire GClass<G> ?

J'avais pensé à la solution triviale :
template<class G>
class DefGClass : public GClass<G, int>
{ };

Mais on est obligé d'utiliser un nom différent.



Si l'implementation de GClass<G, H> et GClass<G, int> est la meme, tu
peux associer a H la valeur par defaut int:

template<class G, class H = int>
class GClass {};

a l'utilisation:
GClass<double, double> g1;
GClass<double> g2; // ici le type de H est implicitement int

Bertrand.