Проблема компілятора C ++ із структурою в класі шаблонів


13

Наступний код не компілюється з 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);

Помилка викликана шаблоном foo шаблону. При написанні <= замість <1 він також компілюється.

Будь-який натяк цінується?

Посилання CompilerExplorer https://godbolt.org/z/v6Tygo


7
Я б сказав, що помилки компілятора, але msvc - це єдиний, хто приймає це: - / Demo . Можливі роботи навколо b.bar::fooабо круглих дужок ( (this->b.foo) < 1)
Jarod42

Відповіді:


1

У GCC я потрапляю

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

Отже, компілятор вважає, що в fooцьому рядку посилається на клас fooвище, і очікує аргумент шаблону. Це схоже на те, що ви бачите.

Коли ви перейдете до цього <=, який лексемою є лексема як один маркер. Наступний етап навіть не бачить a <, тому його не плутає.

Якщо ви змінили клас, щоб він не мав того самого імені, як довгий 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 обманює його.


Я розумію ваше пояснення, але не впевнений, чи означає це, що компілятор повинен вести себе таким чином. Можливо, це має бути полем як помилка для різних компіляторів. Іноді ви не можете бути в курсі того, які шаблонні класи знаходяться в зв'язаному заголовку бібліотеки (загальні назви, такі як cnt, count, counter ...)
eactor

Я думаю, що це помилка, але я не знаю, що говорить специфікація. Наявність імен у сторонніх заголовках спричиняє проблеми - це звичайне явище в C ++ - зазвичай це можна вирішити з кваліфікацією.
Лу Франко
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.