【问题标题】:How to correctly reference a function in an anonymous namespace如何正确引用匿名命名空间中的函数
【发布时间】:2011-07-27 02:38:23
【问题描述】:

考虑一下这段 C++ 代码:

namespace
{
    void f()
    {
    }

    class A
    {
        void f()
        {
            ::f(); // VC++: error C2039: 'f' : is not a member of '`global namespace''
        }
    };
}

GCC 编译得很好。 Visual C++ 2008 编译失败,出现 C2039 错误。这两个编译器中的哪一个在这里是正确的?有什么方法可以正确引用 "global" f 吗?

编辑: Zack 建议尝试一下,它适用于两种编译器。我觉得有点奇怪。

namespace
{
    void f()
    {
    }

    class A
    {
        void f();
    };
}

void A::f()
{
    ::f();
}

【问题讨论】:

  • 不是我知道一个真正的答案,但也许这也很重要:使用不隐藏外部名称的函数名称? :)
  • 我同意。这更像是一个理论问题。
  • 当然,而且我认为这很有趣。 +1 发现这一点。
  • 如果将A::f 的定义拉到class A 之外会发生什么?如果你把它从匿名命名空间声明中拉出来怎么办?
  • 扎克,它有效。但我发现::A::f 可能存在问题,如果有的话。

标签: c++ visual-c++ gcc namespaces language-lawyer


【解决方案1】:

VC++ 2008 在这里是错误的。根据c++03标准3.4.3.4:

以一元作用域为前缀的名称 运算符 :: (5.1) 在 全局范围,在翻译单元中 它在哪里使用。名称应为 在全局命名空间范围内声明或 应该是一个名称,其声明是 在全球范围内可见,因为 使用指令 (3.4.3.2)。指某东西的用途 :: 允许使用全局名称 即使它的标识符有 已隐藏 (3.3.7)。

这里的重要部分是全局命名空间中的 using 指令将使这些符号可以通过范围运算符访问。

并且根据 7.3.1.1/1,匿名命名空间相当于:

namespace *unique* { /* empty body */ }
using namespace *unique*;
namespace *unique* { namespace-body }

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

【讨论】:

    【解决方案2】:

    正如 AcademicRobot 所指出的,Visual C++ 是错误的。作为一种解决方法,添加一个空的未命名命名空间块应该可以解决问题(我没有要测试的 Visual C++ 2008,但这适用于 Visual C++ 2010):

    // empty unnamed namespace to placate compiler
    namespace { }
    
    namespace {
        void f() { }
        struct A {
            void f() { ::f(); }
        };
    }
    

    我已将此问题报告给 Visual C++ 团队。

    【讨论】:

    • 感谢您的解决方案。我刚刚在 VS2008 上对其进行了测试,它也可以在那里工作。我接受了 AcademicRobot 的回答,因为它详细解释了问题。在他回答之后,您的解决方案非常有意义。
    猜你喜欢
    • 1970-01-01
    • 2018-10-28
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 2015-02-10
    • 1970-01-01
    相关资源
    最近更新 更多