C ++ - Compilerproblem mit struct in der Vorlagenklasse

13

Der folgende Code wird nicht mit gcc oder clang kompiliert.

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;
};

Fehlermeldung ist

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

Der Fehler wird durch die Templat-Klasse foo verursacht. Beim Schreiben von <= anstelle von <1 wird auch kompiliert.

Irgendein Hinweis geschätzt?

CompilerExplorer-Link https://godbolt.org/z/v6Tygo

123tv
quelle
7
Ich würde Compiler-Fehler sagen, aber msvc ist der einzige, der dies akzeptiert: - / Demo . Mögliche Umgehungen b.bar::foooder Klammern ( (this->b.foo) < 1)
Jarod42

Antworten:

1

In GCC verstehe ich

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

Der Compiler glaubt also, dass sich das fooin dieser Zeile auf die fooobige Klasse bezieht und erwartet ein Vorlagenargument. Dies ähnelt dem, was Sie sehen.

Wenn Sie es in ändern <=, wird dies vom Lexer als einzelnes Token markiert. Die nächste Stufe sieht nicht einmal ein <, also wird es nicht dadurch verwirrt.

Wenn Sie die Klasse so ändern, dass sie nicht denselben Namen wie die Long-In-Klasse hat, bartritt dieses Problem nicht auf. Außerdem hat @ Jarod42 in seinem Kommentar zu Ihrer Frage Vorschläge (mehr Qualifikation oder Parens).

Compiler werden in Stufen geschrieben, wobei jede Stufe den Code in eine bessere Darstellung für die nächste übersetzt und jede Stufe mit dieser Darstellung immer komplexere Dinge tun kann.

Zu Beginn "lexisiert" der Compiler den Code, der die einzelnen Zeichen in der Datei in einen Token-Stream verwandelt - diese Zeile würde so etwas wie aussehen

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

Und dann geht es zum foo. Es sollte wahrscheinlich tun

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

Aber es sieht für mich so aus, als ob es sieht foo, es schaut nach vorne, sieht das <und die Tatsache, die foo<class T>existiert, und es versucht, ein einzelnes Token daraus zu machen, foo< ...aber dann kann es das nicht finden >, um es zu vervollständigen.

Dies ist nur eine Vermutung - es könnte eine Phase hinter dem Lexer sein, die versucht, Namen zu finden und Token zu kombinieren. In jedem Fall betrügt die mehrfache Verwendung von foo es.

Lou Franco
quelle
Ich verstehe Ihre Erklärung, bin mir aber nicht sicher, ob sich der Compiler so verhalten soll. Vielleicht sollte dies ein Fehlerfeld für die verschiedenen Compiler sein. Manchmal können Sie nicht wissen, welche Vorlagenklassen sich in einem verknüpften Bibliotheksheader befinden (gebräuchliche Namen wie cnt, count, counter ...)
eactor
Ich denke, es ist ein Fehler, aber ich weiß nicht, was die Spezifikation sagt. In C ++ kommt es häufig vor, dass Namen aus Headern von Drittanbietern Probleme verursachen. Diese können Sie normalerweise mit Qualifikation beheben.
Lou Franco