Problème de compilateur C ++ avec struct dans la classe de modèle

13

Le code suivant ne compile pas avec gcc ou clang.

template<class T>
class foo{};

template<class T>
class template_class_with_struct
{
    void my_method() {
        if(this->b.foo < 1);
    };

    struct bar
    {
        long foo;
    } b;
};

Le message d'erreur est

error: type/value mismatch at argument 1 in template parameter list for 'template<class T> class foo'    
    8 |         if(this->b.foo < 1);

L'erreur est causée par la classe templat foo. Lors de l'écriture de <= au lieu de <1, il se compile également.

Un indice apprécié?

Lien CompilerExplorer https://godbolt.org/z/v6Tygo

123tv
la source
7
Je dirais des bugs du compilateur mais msvc est le seul à l'accepter: - / Demo . b.bar::foo(this->b.foo) < 1
Contournements

Réponses:

1

Dans GCC, je reçois

so.cpp:8:27: error: expected '>'
    if(this->b.foo < 1) 
                      ^

Ainsi, le compilateur pense que le foosur cette ligne se réfère à la classe fooci-dessus et attend un argument de modèle. C'est similaire à ce que vous voyez.

Lorsque vous le changez en <=, qui est symbolisé par le lexer comme un seul jeton. La prochaine étape ne voit même pas de <, donc elle n'est pas confondue.

Si vous changez la classe pour ne pas avoir le même nom que le long in bar, alors il n'a pas ce problème. Aussi, @ Jarod42 a des suggestions dans son commentaire à votre question (plus de qualification ou de parens).

Les compilateurs sont écrits en étapes, où chaque étape traduit le code en une meilleure représentation pour la suivante, et chaque étape peut faire des choses de plus en plus complexes avec cette représentation.

Au début, le compilateur "lexe" le code, qui transforme les caractères individuels du fichier en un flux de jetons - il verrait cette ligne comme quelque chose comme

// if(this->b.foo < 1) 
- keyword(if)
- left-paren
- keyword(this)
- operator(->)
- name(b)
- operator(.)

Et puis ça arrive au foo. Cela devrait probablement faire

- name(foo)
- operator(<)
- number(1)
- right-paren

Mais, il me semble que quand il voit foo, il regarde vers l'avant, voit le <et le fait qui foo<class T>existe et il essaie de faire un seul jeton, foo< ...mais il ne peut pas trouver le >pour le compléter.

C'est juste une supposition - cela pourrait être une étape après le lexeur qui essaie de trouver des noms et peut combiner des jetons. Dans tous les cas, les multiples utilisations de foo le trompent.

Lou Franco
la source
Je comprends votre explication, mais je ne sais pas si cela signifie que le compilateur devrait se comporter de cette façon. Peut-être que cela devrait être un champ comme bogue pour les différents compilateurs. Parfois, vous ne pouvez pas savoir quelles classes de modèles se trouvent dans un en-tête de bibliothèque liée (noms communs comme cnt, count, counter ...)
eactor
Je pense que c'est un bug, mais je ne sais pas ce que dit la spécification. La présence de noms provenant d'en-têtes tiers provoque des problèmes est un phénomène courant en C ++ - vous pouvez généralement résoudre avec qualification.
Lou Franco