det*_*zed 20 c++ gcc namespaces visual-c++ language-lawyer
考虑一下这段C++代码:
namespace
{
void f()
{
}
class A
{
void f()
{
::f(); // VC++: error C2039: 'f' : is not a member of '`global namespace''
}
};
}
Run Code Online (Sandbox Code Playgroud)
GCC编译就好了.Visual C++ 2008无法编译吐出C2039错误.这两个编译器中的哪一个在这里是正确的?有没有办法正确引用"全球" f?
编辑: Zack建议尝试,它适用于两个编译器.看起来有点奇怪.
namespace
{
void f()
{
}
class A
{
void f();
};
}
void A::f()
{
::f();
}
Run Code Online (Sandbox Code Playgroud)
VC++ 2008在这里是错误的.根据c ++ 03标准3.4.3.4:
在全局范围内,在使用它的转换单元中查找以一元范围运算符::(5.1)为前缀的名称.该名称应在全局命名空间范围内声明,或者是由于using-directive(3.4.3.2)而在全局范围内声明的名称.使用::允许引用全局名称,即使其标识符已被隐藏(3.3.7).
这里的重要部分是全局命名空间中的using指令将使用scope运算符访问这些符号.
根据7.3.1.1/1,匿名命名空间相当于:
namespace *unique* { /* empty body */ }
using namespace *unique*;
namespace *unique* { namespace-body }
Run Code Online (Sandbox Code Playgroud)
因此,在这两个部分之间,独立函数应该可以在全局命名空间中访问.
正如AcademicRobot指出的那样,Visual C++是错误的.作为一种解决方法,添加一个空的未命名的命名空间块应解决该问题(我没有要测试的Visual C++ 2008,但这适用于Visual C++ 2010):
// empty unnamed namespace to placate compiler
namespace { }
namespace {
void f() { }
struct A {
void f() { ::f(); }
};
}
Run Code Online (Sandbox Code Playgroud)
我已经向Visual C++团队报告了这个问题.