Ошибка компиляции при определении функции-члена, но только в GCC

Следующая программа компилируется без ошибок с MSVS, clang и GCC:

class A;

namespace Y {
    using ::A;
    class A {};
}

int main() {}

Теперь давайте определим функцию-член. Теперь он по-прежнему компилируется с MSVS и clang, но не с GCC:

class A;

namespace Y {
    using ::A;
    class A { void f() {} };
}

int main() {}

GCC выдает следующее сообщение об ошибке:

  • prog.cc:5:22: ошибка: определение 'void A :: f ()' не находится в пространстве имен, включающем 'A' [-fpermissive]

Это почему? Это ошибка в GCC?

Если вторая версия программы нарушает правило стандарта C ++, какое правило оно нарушает и почему MSVS и clang не выдают диагностическое сообщение для этого нарушения?

Это случай двусмысленности стандарта c ++?

Судя по сообщению об ошибке, GCC неправильно считает, что мы нарушили следующее правило:

  • http://eel.is/c++draft/class.mfct#2 "Определение функции-члена, которое появляется вне определения класса, должно появиться в области пространства имен, включающей определение класса."

У нас нет нарушения этого правила, поскольку определение функции-члена находится внутри определения класса. Моя теория состоит в том, что GCC путает объявление класса A; в глобальном пространстве имен с определением класса class A {...} в пространстве имен Y. Я думаю, что у нас есть ошибка в GCC.

В GCC они объявляют одну и ту же сущность. Это можно увидеть, заметив, что в первой версии программы можно было использовать :: A как полный тип в main при компиляции с GCC. То же самое и для MSVS. Однако с помощью Clang они объявляют разные сущности. Это различие может быть связано с неоднозначностью стандарта C ++. Несмотря на такую ​​двусмысленность, мы явно не нарушаем http://eel.is/c++draft/class.mfct#2. Это правило очень четкое.

Связанный вопрос: Класс объявление в той же области, что и использование объявления, компилируется в GCC, но не в MSVS


person Supremum    schedule 05.07.2015    source источник
comment
Должны ли мы угадывать, в чем заключается сообщение об ошибке?   -  person Lightness Races in Orbit    schedule 05.07.2015
comment
Я отредактировал вопрос, включив в него сообщение об ошибке. Я запустил его здесь: melpon.org/wandbox/permlink/W3284yJiSuXuahQu   -  person Supremum    schedule 05.07.2015
comment
Лично мне кажется, что этот код неверен - вы вперед объявляете A вне класса, а затем определяете его в классе; без оператора using это были бы два отдельных класса (т.е. class A и class Y::A, но с оператором using у вас уже есть имя A в области class Y, поэтому последующее определение class A в этой области выглядит так, как будто оно должно либо скрыть это импортированное имя (и, таким образом, скомпилировать) или использоваться в качестве определения для него, и в этом случае это является нарушением того правила, которое вы опубликовали (ну, по крайней мере, < i> если вы удалите слово функция).   -  person celticminstrel    schedule 06.07.2015


Ответы (1)


Обе эти программы плохо сформированы в соответствии со стандартом C ++. Это происходит по той же причине, что и в соответствующем вопросе:

Объявление класса в том же область видимости, поскольку использование объявления компилируется в GCC, но не в MSVS

Все компиляторы должны выдавать ошибку компиляции в обоих случаях: Значит, это указывает на ошибку в MSVS, clang и GCC.

Ошибка в clang подтверждена и исправлена: https://llvm.org/bugs/show_bug.cgi?id=24030

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

person Supremum    schedule 06.07.2015