O código a seguir não compila com 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;
};
Mensagem de erro é
error: type/value mismatch at argument 1 in template parameter list for 'template<class T> class foo'
8 | if(this->b.foo < 1);
O erro é causado pela classe templat foo. Ao escrever <= em vez de <1, ele também compila.
Alguma dica apreciada?
Link do CompilerExplorer https://godbolt.org/z/v6Tygo
b.bar::foo
(this->b.foo) < 1
Respostas:
No GCC, recebo
Portanto, o compilador pensa que a
foo
linha nessa linha se refere à classefoo
acima e espera um argumento de modelo. Isso é semelhante ao que você está vendo.Quando você altera para
<=
, que é tokenizado pelo lexer como um único token. O próximo estágio nem vê um<
, por isso não é confundido com ele.Se você alterar a classe para não ter o mesmo nome que o long in
bar
, ele não terá esse problema. Além disso, @ Jarod42 tem sugestões no seu comentário à sua pergunta (mais qualificação ou parens).Os compiladores são escritos em estágios, onde cada estágio converte o código em uma melhor representação para o próximo, e cada estágio pode fazer coisas cada vez mais complexas com essa representação.
No início, o compilador "anexa" o código, que transforma os caracteres individuais no arquivo em um fluxo de tokens - veria essa linha como algo como
E então chega ao
foo
. Provavelmente deveria fazerMas, parece-me que quando vê
foo
, olha para frente, vê o<
fato quefoo<class T>
existe e tenta criar um único token,foo< ...
mas não consegue encontrar o>
que o completa.Isso é apenas um palpite - pode ser um estágio passado do lexer que tenta encontrar nomes e pode combinar tokens. De qualquer forma, os múltiplos usos do foo estão enganando-o.
fonte