c++ - GCC不喜欢使用匿名命名空间转发声明来结交 friend ,但是MSVC愿意。什么?

标签 c++ language-lawyer

GodBolt.org上测试时,此代码在MSVC上编译,但不在GCC上编译
Baz类是在匿名 namespace 中声明的,这使GCC认为它是与我在下面定义的类不同的类,但MSVC似乎将它们连接起来。

namespace { class Baz; }

class Foo { protected: int x; };
class Bar : public Foo { friend class Baz; };

namespace {
  class Baz { void f() { Bar b; b.x = 42; } };
}
根据标准正确的是什么?

最佳答案

问题在于,您正在为友元声明使用精心设计的类型说明符,而GCC则使用它在全局 namespace 中声明类BazAn elaborated type specifier is a declaration unless a previous declaration is found in the inner most enclosing namespace。显然尚不清楚Baz的声明是否应视为在全局命名空间中。
要解决此问题,只需在好友声明中使用类的名称即可:

namespace { class Baz; }

class Foo { protected: int x; };
class Bar : public Foo { friend Baz; };

namespace {
  class Baz { void f() { Bar b; b.x = 42; } };
}
在 friend 声明中使用详尽的类型说明符是一种习惯性的病理习惯。除非类型名称也是变量名称,否则没有理由使用详细的类型说明符。

关于c++ - GCC不喜欢使用匿名命名空间转发声明来结交 friend ,但是MSVC愿意。什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63397661/

相关文章:

c++ - 私有(private)移动构造函数是为了防止移动吗?

c++ - 实例化点可以延迟到翻译单元结束吗?

c - 在C89中有效的程序,但在C99中无效

c++ - 测试 C/C++ 源代码

c++ - lambda 中的这个 size_t 是做什么的? C++代码

c++ - 将 VS 32 位项目转换为 64 位项目

c++ - 标准的意图是任何形式的 `nested-type-specifier followed by an identifier` 都可以称为合格 ID

c++ - 我不明白为什么这个程序会打印 8762 作为结果

rust - 为什么固定大小的数组可以入栈,而str不可以?

c++ - 友元函数模板、声明的特化和范围