首页 > 解决方案 > 如果函数在匿名命名空间中声明,是否可以在全局命名空间中定义?

问题描述

在生产代码中,我在 .cpp 文件中找到了这个:

namespace
{
    void foo(); // declared in anonymous namespace, defined below
}

void bar() // declared in corresponding .h file, defined here
{
    ::foo(); // call foo
}

void ::foo() // intended to refer to the anonymous foo above
{
}

我们正在使用 Visual Studio 2017。我偶然发现了这一点,因为智能感知给了我一个警告,foo因为它找不到函数定义。但是,它编译和链接没有错误,并且代码完成了它应该做的事情。

我对它进行了测试,发现 gcc 和 clang 拒绝此代码的原因与智能感知给我警告的原因相同。

所以我的问题是:哪个编译器是正确的,为什么?


此外,出于兴趣,我向foo全局命名空间添加了另一个声明,如下所示:

namespace
{
    void foo();
}

void foo(); // another declaration

void bar()
{
    ::foo(); // which foo will be called?
}

void ::foo() // which foo will be defined?
{
}

现在,gcc 给了我一个错误:

错误:“void foo()”声明中的明确限定

Clang 编译它,但给了我一个警告:

警告:成员 'foo' 的额外资格 [-Wextra-qualification]

msvc 编译它就好了。

同样,哪个编译器(如果有的话)在这里是正确的?

标签: c++gccvisual-c++clanglanguage-lawyer

解决方案


查看未命名命名空间上的cppreference 页面

此定义被视为具有唯一名称的名称空间的定义和在当前范围内指定此未命名名称空间的 using 指令。

因此,“匿名”命名空间不是全局命名空间,甚至也不是未命名的。相反,它具有编译器提供的唯一名称。匿名命名空间中的函数也不::foo()是这样。MSVC 在这里不正确。

而且你不能在它的匿名命名空间之外定义你的匿名命名空间函数


推荐阅读