【问题标题】:Class declaration in same scope as using declaration compiles in GCC but not MSVS与使用声明在 GCC 中编译但在 MSVS 中不编译的类声明
【发布时间】:2015-09-22 01:59:53
【问题描述】:

以下程序是否符合 c++ 标准?

namespace X { class A; }

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

int main() {}

我使用不同的编译器得到不同的结果:

  • gcc 编译它没有错误。
  • visual c++ 给出错误 C2888: 'X::A': symbol cannot be defined in namespace 'Y'

我在 c++ 标准中没有发现我的程序违反的任何规则。

如果程序格式正确,为什么visual studio会报错?

如果程序格式不正确,它违反了c++标准中的什么规则,为什么gcc没有报错?

我不想让我的程序编译。我只是想看看它是否符合 c++ 标准,以及为什么我测试的两个编译器的行为不同。

【问题讨论】:

  • 问题标题令人困惑。 X::AY::A 是两种不同的类型;没有发生“前向声明和后来的定义”。
  • 感谢您的建议。我现在改了标题。
  • 你试过using ::X::A吗?
  • 如果你也将enum A { FOO }; 添加到命名空间Y 中会更有趣。现在 Clang 编译它,并且 GCC 抱怨 A 之前已声明。
  • 也报告给 GCC :-)

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


【解决方案1】:

我认为该程序的格式不正确。 [basic.scope.declarative]/4 说:

给定单个声明区域中的一组声明,每个声明都指定相同的非限定名称,

——它们都应该指代同一个实体,或者都指代函数和函数模板;或

——只有一个声明应该声明一个不是typedef名称的类名或枚举名,而其他声明都应该引用同一个变量或枚举数,或者都引用函数和函数模板;在这种情况下,类名或枚举名是隐藏的

不限定名A的两个声明引用了不同的实体,都是类。

(有趣的是,GCC 6.0 和 Clang 3.7 似乎都没有以这种方式诊断它。两者都接受编写的代码(不诊断具有相同名称的两个不同类的声明)。如果您将 X::A a; 添加到main,然后 Clang 抱怨 X::A 的类型不完整。)

【讨论】:

  • 声明不是A类吗?和 A 类 {} 位于两个不同的声明区域?
  • using 不是声明
  • 声明类A;在声明区域 { class A; } 和声明类 A {};是在声明区域 { 使用 X::A; A类{}; }.
  • 使用 X::A;也是一种宣言。也许你在哪里使用 X::A; 来引用这两个声明;和A类{};它们在同一个声明区域中,但它们真的指的是不同的实体吗?天气标准是否明确A级{};是 A 类的重新声明; ?
  • 可以说这是违反 [basic.scope.declarative]/4。那么不需要诊断吗?在这种情况下,这是 GCC 和 Clang 中的错误。
【解决方案2】:

不太确定,但您可以尝试以下方法:

namespace X { class A; }

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

int main() 
{
  return 0;
}

【讨论】:

  • 建议的程序根据 c++ 标准格式不正确(它违反了 7.3.1.2 p 2)。请参阅eel.is/c++draft/namespace.memdef#2 它不能在 gcc 上编译,也不能在 Visual c++ 上编译。我也不想让我的程序编译。我只是想看看它是否符合 c++ 标准,以及为什么我测试的两个编译器的行为不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 1970-01-01
  • 2023-03-19
  • 2020-02-17
  • 1970-01-01
  • 2011-02-01
  • 1970-01-01
相关资源
最近更新 更多