Проблема компилятора C ++ со структурой в классе шаблона - PullRequest
13 голосов
/ 06 февраля 2020

Следующий код не компилируется с g cc или лязгом.

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 класс фу. При записи <= вместо <1 он также компилируется. </p>

Любая подсказка приветствуется?

Ссылка CompilerExplorer https://godbolt.org/z/v6Tygo

1 Ответ

1 голос
/ 06 февраля 2020

В G CC я получаю

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

Итак, компилятор считает, что foo в этой строке относится к классу foo выше и ожидает аргумент шаблона. Это похоже на то, что вы видите.

Когда вы изменяете его на <=, который лексер маркирует как один токен. Следующий этап даже не видит <, поэтому он его не смущает.

Если вы измените класс на имя, отличное от long в bar, он не будет есть эта проблема. Кроме того, @ Jarod42 имеет предложения в своем комментарии к вашему вопросу (дополнительная квалификация или параны).

Компиляторы пишутся поэтапно, где каждый этап переводит код в лучшее представление для следующего, и каждый этап может выполнять все более и более сложные вещи с этим представлением.

В начале, компилятор "лексирует" код, который превращает отдельные символы в файле в поток токенов - он будет видеть эту строку как что-то вроде

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

И тогда он достигает foo. Вероятно, он должен сделать

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

Но мне кажется, что когда он видит foo, он смотрит в будущее, видит < и тот факт, что foo<class T> существует, и он пытается создать одиночный токен из foo< ..., но затем он не может найти > для его завершения.

Это всего лишь предположение - это может быть этап мимо лексера, который пытается найти имена и может объединить жетоны В любом случае, многократное использование foo обманывает его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...