c++ - 为什么 gcc 无法从其前向声明中检测到朋友类命名空间?
问题描述
我有以下代码可以用 VS2015 编译,但不能用 gcc(任何版本)编译。对我来说,命名空间class A_Creator
是正确定义的(即根命名空间),因为它已经在程序的顶部前向声明。为什么 gcc 无法A_Creator
正确检测到类的命名空间?哪个编译器是对的?
#include <list>
class A_Creator;
namespace X
{
class A
{
private:
int mX;
A(int x) :
mX(x)
{}
// GCC complains about this line, and it should be changed to ::A_Creator
// On VS2015, both of them are working
friend class A_Creator;
};
} // namespace X
class A_Creator
{
public:
std::list<X::A> TestOnList(int z)
{
std::list<X::A> a_list;
a_list.push_back(X::A(z));
return a_list;
}
};
int main()
{
A_Creator a_cr;
auto x = a_cr.TestOnList(12);
}
解决方案
从C++11 [namespace.memdef]/3开始:
如果
friend
声明中的名称既不是限定词也不是模板标识,并且声明是函数或详细类型说明符,则确定实体是否先前已声明的查找不应考虑最内层封闭命名空间之外的任何范围。[注意:其他形式的友元声明不能声明最内层封闭命名空间的新成员,因此遵循通常的查找规则。——尾注]
由于您在friend
声明 ( friend class A_Creator;
) 中详细说明了类型说明符,因此应仅在最里面的封闭命名空间中搜索先前的声明::X
。所以,gcc 是对的。
[namespace.memdef]/3 中示例的相关摘录,其中包含函数而不是类的全局前向声明:
void h(int);
namespace A {
class X {
class Y {
friend void h(int); // A::h is a friend
// ::h not considered
};
};
}
推荐阅读
- spring-boot - 处理 Spring Websocket 应用程序副本之间的流量
- r - 如何结合 2 个 lapply() 函数来创建箱线图?
- android - FlatButton 没有响应点击
- python - Typehint 使用 importlib 动态导入模块
- python - 有没有办法从 Sympy 中的关系返回布尔值?
- python - 如何在地图上绘制间隔?
- android - Kotlin Flow 的手动重试
- java - 在 UBUNTU 中从 VS Code 运行 Kotlin 会产生 kotlinc:未找到
- r - 将比赛从多列重新编码为一列
- java - 我可以从文件中保存超过数组大小的数字吗?