Bonjour,
Premièrement, j’utilise le compilateur gcc/g++ version 4.5.0 sur Linux.
En explorant le monde merveilleux des modèles (template), je suis tombé sur un os :
on peut définir des fonctions modèles sans arguments (de fonction) et les appeler comme ceci :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| // Déclaration
template<typename _Type>
void Function();
// Définition
template<typename _Type>
void Function()
{
std::cout << "void Function<_Type>()\n";
}
// Instanciation explicite
template
void Function<int>();
// Appel
int main()
{
Function<int>();
return 0;
} |
Par contre, j’ai remarqué qu’on pouvait déclarer, définir et instancier explicitement des constructeurs modèles sans arguments (de fonction) de la même manière, mais je suis incapable de les appeler :
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
| // Définition dune classe
class TClass
{
public:
template<typename _Type>
TClass();
};
// Définition du constructeur modèle
template<typename _Type>
TClass::TClass()
{
std::cout << "TClass::TClass<_Type>()\n";
}
// Instanciation explicite
template
TClass::TClass<int>(); // Ceci est légal
// Utilisation
int main()
{
TClass Class1; // Illégal, le constructeur par défaut nest pas généré à
// cause de la présence du constructeur modèle (ça me semble
// normal)
TClass Class2<int>; // Illégal, le '<' est pris pour un opérateur
// 'inférieur à'
TClass Class3(TClass()); // Légal, le constructeur par copie par défaut est
// utilisé, ce qui me semble normal, mais le
// constructeur par défaut est généré ici alors
// quil ne lest pas pour Class1, bizarre !!!
TClass Class4(TClass<int>()); // Illégal, 'TClass<int>' est pris pour le
// nom dune classe modèle
TClass Class5(TClass::TClass<int>()); // Illégal, un constructeur ne peut
// pas être appelé directement
return 0;
} |
Pour info, voici les messages d’erreur renvoyés par g++ :
Pour Class1 :
1 2
| Test.cpp:25:11: error: no matching function for call to TClass::TClass()
Test.cpp:5:1: note: candidate is: TClass::TClass(const TClass&) |
Pour Class2 :
Test.cpp:29:17: error: expected initializer before < token
Pour Class4 :
Test.cpp:37:18: error: TClass is not a template
Pour Class5 :
1 2 3 4
| Test.cpp:40:38: error: cannot call constructor TClass::TClass directly
Test.cpp:40:38: error: for a function-style cast, remove the redundant ::TClass
Test.cpp:40:38: error: no matching function for call to TClass::TClass()
Test.cpp:5:1: note: candidate is: TClass::TClass(const TClass&) |
Notez que :
- J’ai essayer de ne laisser qu’une seule de ces 5 déclarations à la fois et j’ai bien les mêmes messages d’erreur.
- Lorsque je ne laisse que Class3, que je compile et que j’exécute, c’est bien le constructeur généré par défaut que s’exécute, pas le constructeur modèle avec un paramètre quelconque (pas de sortie sur la sortie standard).
- Lorsque je mets la déclaration de Class1 après celle de Class3, le constructeur par défaut n’est toujours pas généré pour Class1.
- J’ai bien compris quelques subtilités des modèles, comme le besoin du mot clé template dans certains cas pour appeler une fonction modèle sans arguments (de fonction), du genre de ce qui est expliqué sur la FAQ de comeau.
J’ai donc essayé de rajouter ce mot clé à différents endroits, mais rien n’est légal.
Bref, je dois passer à côté de quelque chose, car il me semble bizarre qu’on puisse déclarer, définir et instancier explicitement une fonction modèle qu’on ne peut pas appeler.
- Quelqu’un sait comment appeler ce constructeur modèle ?
- Est-ce que le comportement de g++ est conforme à la norme ?
- Est-ce que d’autre compilateurs acceptent une de ces syntaxes d’appel (je n’en ai pas sous la main) ?
- Est-ce que la génération du constructeur par défaut dans un cas et pas dans l’autre (Class1 et Class3) est correct ou est-ce un bug de g++ ?
PS : ceci est une question purement technique, je n’ai pas d’exemple d’utilisation pratique en vue, c’est par pure curiosité que je la pose.
Partager