Erreur du compilateur G ++ avec le membre de la classe de base des modèles
-
14-11-2019 - |
Question
J'essaie de compiler un code C ++ visuel Microsoft à l'aide de G ++. Maintenant, je suis tombé sur une erreur de compilateur que je ne comprends vraiment pas. Le code (simplifié) ressemble à ceci:
template<int X> struct A {
template<class Ret> static Ret call() {
return 0;
}
};
template<int X> struct B : A<X> {
int f() {
return A<X>::call<int>();
}
};
Lorsque j'essaie de compiler cela avec G ++ (version 4.4.5), j'obtiens l'erreur suivante:
main.cpp: In member function int B<X>::f():
main.cpp:16: error: expected primary-expression before int
main.cpp:16: error: expected ; before int
main.cpp:16: error: expected unqualified-id before > token
Si je supprime le type de modèle (RET) de la méthode A :: Call, le code se compile très bien. Quelqu'un peut-il voir ce qui ne va pas ici?
Merci!
La solution
Vous avez besoin du template
mot-clé:
return A<X>::template call<int>();
call
est un nom dépendant, ce qui signifie que sa signification dépend d'un paramètre de modèle, qui n'est pas connu lorsque le processus du compilateur f()
. Vous devez indiquer que call
est un modèle de fonction en le préfixant avec le template
mot-clé.
La même chose se produit lorsque vous essayez d'accéder à un type imbriqué: vous devez ajouter le typename
mot-clé pour indiquer que le nom indique un type:
template <typename T>
struct A { typedef int type; };
template <typename T>
void f()
{
typename A<T>::type i = 0; // notice "typename" here
}
Et parfois, vous devez même mélanger les deux:
template <typename T>
struct A
{
template <typename U>
struct inner { };
};
template <typename T>
void f()
{
typename A<T>::template inner<int> var;
}
L'utilisation de ces deux mots clés est entièrement expliquée dans les réponses à cette question: Où et pourquoi dois-je mettre les mots clés «modèle» et «typename»? (Merci à @ Björn Pollex pour avoir trouvé le lien).
Autres conseils
A
est un modèle, et sans savoir X
le compilateur ne peut pas déterminer le contenu de A<X>
. Surtout ça ne sait pas que call
finira par être un modèle.
Pour dire qu'au compilateur, vous devez utiliser le template
mot-clé:
template<int X> struct B : A<X> {
int f() {
return A<X>::template call<int>();
}
};
Vous devez spécifier que la fonction que vous appelez est un modèle, car elle fait partie d'une classe de modèle. Le compilateur n'est pas conscient qu'un donné A<X>
a une fonction de modèle nommée call
, et donc vous devez l'aider.
template<int X> struct B : A<X> {
int f() {
return A<X>::template call<int>();
}
};