J'ai le code suivant:
template <typename TC>
class C
{
struct S
{
template <typename TS>
void fun() const
{}
};
void f(const S& s)
{
s.fun<int>();
}
};
// Dummy main function
int main()
{
return 0;
}
Lors de la construction de ceci avec gcc 9.2 et clang (9.0), j'obtiens une erreur de compilation en raison du template
mot clé requis pour l'invocation fun
. Clang montre:
error: use 'template' keyword to treat 'fun' as a dependent template name
s.fun<int>();
^
template
Je ne comprends pas pourquoi le compilateur pense que fun
c'est un nom dépendant dans le contexte de f
, car ce f
n'est pas un modèle lui-même. Si je change C
pour être une classe régulière au lieu d'un modèle, l'erreur disparaît; cependant, je ne vois pas pourquoi il devrait y avoir une erreur en premier lieu puisque ni S
ni f
dépendre TC
.
Curieusement, MSVC 19.22 compile cela très bien.
Remarque
Avant de voter pour fermer en tant que dupe de Où et pourquoi dois-je mettre les mots-clés "modèle" et "nom de type"? veuillez considérer qu'il s'agit d'un cas spécial où même s'il S
s'agit bien d'un nom dépendant, dans le contexte de f
celui-ci ne serait pas dépendant sinon du fait qu'ils sont membres de l'instanciation actuelle.
Réponses:
Considérez :
s.a<0>(i)
est analysé comme une expression contenant deux opérations de comparaison<
et>
, et cela convient pour # 1 mais échoue pour # 2.Si cela est changé en
s.template a<0>(i)
alors # 2 est OK et # 1 échoue. Ainsi, letemplate
mot clé n'est jamais redondant ici.MSVC est capable d'interpréter l'expression dans les
s.a<0>(i)
deux sens au sein du même programme. Mais ce n'est pas correct selon la norme; chaque expression ne doit avoir qu'une seule analyse pour le compilateur.la source
C
ou l'autre, mais vous ne pouvez jamais instancier les deux. Letemplate
mot-clé ici n'est toujours pas nécessaire à mon humble avis, car celui quiS
est choisi dépend de celui queC
vous instanciez. Sans letemplate
mot clé, vous seriez en mesure d'instancier les deux, et le comportement de f serait différent pour chaque instance.<
soit un opérateur de comparaison dans une instanciation de modèle et un support d'angle d'ouverture dans une autre instanciation. Cela permet de garantir que les compilateurs peuvent analyser les modèles vers un AST (avec des espaces réservés pour les types de modèles).fun
peut ou peut ne pas être une fonction de modèle (ou peut ne pas exister du tout) selon le paramètre de modèle declass C
.C'est parce que vous pouvez vous spécialiser
S
(sans vous spécialiserC
):Parce que le compilateur veut savoir s'il
fun
s'agit d'un modèle ou non lors de la première consultationclass C
(avant de remplacer le paramètre de modèle),template
est requis.la source
S
seront accessibles parf
. S'ils ne le peuvent pas, cette restriction n'a aucun sens carf
ils ne pourront pas les voir de toute façon.f
trouve.