【问题标题】:Compile error when defining a member function, but only in GCC定义成员函数时编译错误,但仅在 GCC 中
【发布时间】:2015-09-22 19:02:36
【问题描述】:

使用 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 错误地认为我们违反了以下规则:

我们没有违反这条规则,因为成员函数定义在类定义中。我的理论是 GCC 混淆了声明类 A;在全局命名空间中,类定义 class A { ... } 在命名空间 Y 中。我认为我们在 GCC 中有一个错误。

使用 GCC,它们声明了相同的实体。这可以通过观察在程序的第一个版本中使用 GCC 编译时在 main 中使用 ::A 作为完整类型来看出。 MSVS 也一样。然而,对于 Clang,它们声明了不同的实体。这种差异可能是由于 c++ 标准中的歧义。不管这样的模棱两可,我们显然没有违反 http://eel.is/c++draft/class.mfct#2 。这条规则很明确。

相关问题:Class declaration in same scope as using declaration compiles in GCC but not MSVS

【问题讨论】:

  • 我们必须猜测错误信息是什么吗?
  • 我已编辑问题以包含错误消息。我在这里运行它:melpon.org/wandbox/permlink/W3284yJiSuXuahQu
  • 就个人而言,在我看来代码不正确-您在类外转发声明A,然后在类中定义它;如果没有 using 语句,它们将是两个单独的类(即 class Aclass Y::A,但是使用 using 语句,您已经在 class Y 的范围内拥有名称 A,因此随后定义了 @ 987654332@ 在该范围内看起来应该隐藏该导入的名称(并因此编译)被视为它的定义,在这种情况下它违反你发布的那个规则(好吧,至少如果你删除了“函数”这个词)。

标签: c++ gcc language-lawyer using-declaration


【解决方案1】:

根据 c++ 标准,这两个程序都是格式错误的。这是因为与相关问题中的原因相同:

Class declaration in same scope as using declaration compiles in GCC but not MSVS

所有编译器在这两种情况下都应该给出编译错误:所以这表明 MSVS、clang 和 GCC 中存在错误。

clang中的bug已经确认并修复:https://llvm.org/bugs/show_bug.cgi?id=24030

GCC 给第二个程序一个奇怪的错误消息的原因是当它未能检测到第一个和第二个程序中都存在的错误时会感到困惑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多