El siguiente código no se compila con gcc o 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;
};
Mensaje de error es
error: type/value mismatch at argument 1 in template parameter list for 'template<class T> class foo'
8 | if(this->b.foo < 1);
El error es causado por templat class foo. Al escribir <= en lugar de <1, también se compila.
¿Alguna pista apreciada?
CompilerExplorer link https://godbolt.org/z/v6Tygo
b.bar::foo
o paréntesis ((this->b.foo) < 1
)Respuestas:
En GCC, me sale
Entonces, el compilador piensa que
foo
en esa línea se refiere a la clasefoo
anterior y espera un argumento de plantilla. Esto es similar a lo que estás viendo.Cuando lo cambia a
<=
, que el lexer tokeniza como un token único. La siguiente etapa ni siquiera ve a<
, por lo que no se confunde con ella.Si cambia la clase para que no tenga el mismo nombre que la entrada larga
bar
, entonces no tiene este problema. Además, @ Jarod42 tiene sugerencias en su comentario a su pregunta (más calificación o parens).Los compiladores se escriben en etapas, donde cada etapa traduce el código a una mejor representación para la siguiente, y cada etapa puede hacer cosas cada vez más complejas con esa representación.
Al principio, el compilador "lexes" el código, que convierte los caracteres individuales en el archivo en una secuencia de tokens; vería esta línea como algo así como
Y luego llega a la
foo
. Probablemente debería hacerPero, me parece que cuando ve
foo
, mira hacia adelante, ve el<
hecho y el hecho de quefoo<class T>
existe e intenta hacer una sola fichafoo< ...
pero luego no puede encontrar la>
para completarla.Esto es solo una suposición: podría ser una etapa más allá del lexer que intenta encontrar nombres y puede combinar tokens. En cualquier caso, los múltiples usos de foo lo están engañando.
fuente