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
b.bar::foo
oder Klammern ((this->b.foo) < 1
)Antworten:
In GCC verstehe ich
Der Compiler glaubt also, dass sich das
foo
in dieser Zeile auf diefoo
obige 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,
bar
tritt 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
Und dann geht es zum
foo
. Es sollte wahrscheinlich tunAber es sieht für mich so aus, als ob es sieht
foo
, es schaut nach vorne, sieht das<
und die Tatsache, diefoo<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.
quelle