C++ 存在重载命名空间函数时是否需要std::限定符?

C++ 存在重载命名空间函数时是否需要std::限定符?,c++,c++11,name-lookup,C++,C++11,Name Lookup,如果我有一些代码,比如: using namespace std; namespace myNamespace { vector<float> sqrt( vector<float> v ) { return v; } void func() { vector<float> myVec = { 1, 2, 3, 4 }; std::cout << sqrt( myVec )[0] <

如果我有一些代码,比如:

using namespace std;

namespace myNamespace
{
    vector<float> sqrt( vector<float> v ) { return v; }

    void func()
    {
        vector<float> myVec = { 1, 2, 3, 4 };
        std::cout << sqrt( myVec )[0] << std::endl;
        float myFloat = 4.0f;
        std::cout << sqrt( myFloat ) << std::endl; // need to use std::sqrt()
    }
}
使用名称空间std;
名称空间myNamespace
{
向量sqrt(向量v){返回v;}
void func()
{
向量myVec={1,2,3,4};

std::cout您可以通过
myNamespace
中的
语句
使用std::sqrt;
std::sqrt
引入您的命名空间:

namespace myNamespace
{
    vector<float> sqrt( vector<float> v ) { return v; }
    using std::sqrt;
    ...
名称空间myNamespace
{
向量sqrt(向量v){返回v;}
使用std::sqrt;
...
<> P>编译器在代码> STD::CUT

C++中选择适当的<代码> > >代码,不关心参数类型,只有名称是重要的。当编译器寻找一个名为“代码> Sqrt”的函数时,它总是首先找到你的版本(因为查找从封闭的命名空间开始),然后停在那里。 您必须通过在命名空间中使用指令将

std::
中的名称引入作用域来帮助编译器:

namespace myNamespace
{
  using std::sqrt
  ...
}
然后,将执行标准重载解析以区分
sqrt
和,并选择要调用的正确
sqrt
函数

为了避免任何歧义,您应该始终限定名称(
std::sqrt
myNamespace::sqrt


注意事项:

  • 正如Simple所指出的,在第一种情况下允许名称查找(因为
    vector
    std::
    中),但它不会改变您所面临的问题

  • std::
    中声明自己的
    sqrt
    函数是一个非常糟糕的主意(标准禁止,模板专门化除外)


std
名称空间中声明您自己的函数肯定是错误的。您可以在全局名称空间中声明它,因为您出于某种原因在其中转储了
std
。或者您可以将
使用std::sqrt;
添加到您的名称空间中,与
sqrt
一起。我只需正确限定名称。您还可以不要使用
使用名称空间somethingssomethingssomethingssomethingssomethingssomethingssomething
并始终使用std::前缀,避免像这样的废话。有没有办法将所有std::名称引入当前名称空间?比如使用std:*?它确实关心参数类型。在对
sqrt
的第一次调用中,编译器将同时找到这两个
myNamespace::sqrt
std::sqrt
通过ADL(因为
vector
std
中)。它只选择
myNamespace::sqrt
,因为它更匹配。