如何正确引用匿名命名空间中的函数

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)

aca*_*bot 9

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)

因此,在这两个部分之间,独立函数应该可以在全局命名空间中访问.


Jam*_*lis 7

正如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++团队报告了这个问题.