C ++在名称空间中声明与全局名称空间中的函数同名的函数

C++ Declaring function in namespace with same name as function in global namespace

我对 C++ 中的函数声明范围有疑问。假设使用 #include <cmath> 将函数符号引入全局命名空间。按照我的理解,原则上应该只在std命名空间引入symbol,但在实践中,根据我自己的经验,有些symbol出现在全局命名空间中。这个答案似乎证实了这一点:cmath header confusion.

现在,当我在 namespace foo { } 中声明一个函数(具有与全局命名空间中的函数相同的原型)时会发生什么?例如,假设 <cmath> 中的 sqrt() 最终出现在全局命名空间中,并且我有:

#include <cmath>

namespace foo {

    template <class T>
    T sqrt( T x ) {
        // do something extra...
        return std::sqrt( x );
    }

}

// ...

void foo::bar() {
    double a = 4.0;
    double b = sqrt( a );
}

模板解析为符号 double sqrt( double x ),这似乎与全局命名空间中的符号冲突。这似乎有效,但这通常是一种不好的做法吗?

更一般地说,在同一命名空间内使用时,在命名空间内声明的函数是否优先于全局函数?这是否以任何方式违反了 C++ 标准?

这里有两个不同的问题。

首先,拉入某些 headers 确实会在全局命名空间和 std 命名空间中注入符号。 sausage-making 与 C++ 在 C 中的遗留和根源有关;并尝试尽可能少地用 C++ 编译遗留 C 代码。

其次,这是真的...

a function declared inside a namespace take precedence over a global function, when used from inside the same namespace?

没错。而且,不,这不是

violate the C++ standard in any way?

事实上,C++ 标准明确规定这是事情应该如何工作的。解析来自名称空间的引用首先搜索相同的名称空间,作为第一项业务。如果是嵌套命名空间,则为 parent 命名空间。然后,最终是全局命名空间。

然后,using namespace让事情变得复杂。这就是为什么 you should not do that.

最后,为了让事情变得有趣,还有 argument dependent lookup 通过搜索不在当前命名空间、parent 命名空间或全局命名空间,但在与函数参数相同的命名空间中。

从来没有人指责 C++ 简单。