Следующий код не компилируется с gcc или 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;
};
Сообщение об ошибке
error: type/value mismatch at argument 1 in template parameter list for 'template<class T> class foo'
8 | if(this->b.foo < 1);
Ошибка вызвана классом templat foo. При записи <= вместо <1 он также компилируется.
Любой намек оценили?
Ссылка CompilerExplorer https://godbolt.org/z/v6Tygo
b.bar::foo
или скобки ((this->b.foo) < 1
)Ответы:
В GCC я получаю
Таким образом, компилятор считает, что в
foo
этой строке относится к классуfoo
выше и ожидает аргумент шаблона. Это похоже на то, что вы видите.Когда вы меняете его на
<=
, который лексер маркирует как один токен. Следующий этап даже не видит<
, поэтому его это не смущает.Если вы измените класс на имя, отличное от long
bar
, то у него не будет этой проблемы. Кроме того, у @ Jarod42 есть предложения в его комментарии к вашему вопросу (больше квалификации или параны).Компиляторы написаны поэтапно, где каждый этап переводит код в лучшее представление для следующего, и каждый этап может делать все более и более сложные вещи с этим представлением.
В начале, компилятор "лексирует" код, который превращает отдельные символы в файле в поток токенов - он будет видеть эту строку как что-то вроде
И тогда дело доходит до
foo
. Вероятно, следует сделатьНо мне кажется, что когда он видит
foo
, он смотрит в будущее, видит<
и тот факт, которыйfoo<class T>
существует, и он пытается сделать из него один токен,foo< ...
но затем он не может найти тот,>
чтобы завершить его.Это всего лишь предположение - это может быть этап мимо лексера, который пытается найти имена и может комбинировать токены. В любом случае, многократное использование foo обманывает его.
источник