gcc не компилирует override

struct override {};

struct A {
    virtual override override() = 0;
};

struct B : A {
    auto override() -> struct override override{
        return ::override{};
    }
};

int main() {
    B().override();
}

Почему clang компилирует без проблем, а gcc - нет? Кто прав и почему?

error: declaration of 'virtual override A::override()' changes meaning of 'override'

Также интересно, нужен ли :: и почему. Никто не хочет компилировать без него.

error: reference to non-static member function must be called; did you mean to call it with no arguments?


Ответы (1 шт):

Автор решения: KoVadim

Это код с собеседования? Не стоит использовать полуключевое слово (override) как имя функции и имя структуры одновременно. Ни к чему хорошему это не приведет. В данном случае компилятор gcc об этом явно и предупреждает. Но если очень-очень хочется выстрелить себе в ногу в будущем, то пока можно это спрятать, явно подсказав компилятору, что там именно такое

struct A {
    virtual struct override override() = 0;
};

Но не пишите такое в продакшн код и не показывайте на собеседованиях.

Но на самом деле здесь ошибка просто мастерски спрятана (если бы меня таким кодом собеседовали, я бы встал и вышел (и я так делал, очень рекомендую!)). Можно смело override заменить на test и будет такая же ошибка.

Есть такая цитата в стандарте [3.3.7 Class Scope]

A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

Если кратко - одно и тоже имя в пределах класса должно значить одно и тоже. Но от компилятора не требуется диагностика.

Поэтому gcc прав, он знает, что программа плохая и говорит об этом (хотя и не должен был этого делать).

clang не говорит о том, что программа плохая (но и не должен был), но при этом скомпилировал программу.

двойное двоеточие в return ::override{}; нужно, что бы компилятор догадался, что здесь именно внешнее имя, а не имя функции или ещё что то.

→ Ссылка