具有父命名空间的嵌套命名空间中的重载解析

Bar*_*uch 3 c++ overload-resolution name-lookup

我认为在嵌套命名空间中,任何属于父(或全局)命名空间的内容都被同等考虑用于重载解析,但此示例似乎另有说明。

这工作正常:

#include <iostream>

void foo(int) { std::cout << "int\n"; }
void foo(float) { std::cout << "float\n"; }

namespace NS {
    void bar() {
        foo(0);
    }
}

int main() {
    NS::bar();
}
Run Code Online (Sandbox Code Playgroud)

调用foo(0)匹配,foo(int)因为它是一个更好的匹配,一切都按预期工作。但是,如果我将 的声明移动foo(float)到命名空间中:

#include <iostream>

void foo(int) { std::cout << "int\n"; }

namespace NS {
    void foo(float) { std::cout << "float\n"; }
    void bar() {
        foo(0);
    }
}

int main() {
    NS::bar();
}
Run Code Online (Sandbox Code Playgroud)

foo(0)现在的呼吁foo(float)

我已经搜索过https://en.cppreference.com/w/cpp/language/overload_resolution和许多其他此类页面,以找到解释这一点的规则,但我似乎错过了它。有人可以解释一下许多复杂的重载解析规则中的哪一个会导致这种情况,还是其他原因?

编辑
我刚刚发现它更奇怪。即使foo命名空间内部根本不匹配,它仍然不会使用外部的。这完全无法编译:

#include <iostream>

void foo(int) { std::cout << "int\n"; }

namespace NS {
    void foo(float, float) { std::cout << "float\n"; }
    void bar() {
        foo(0);
    }
}

int main() {
    NS::bar();
}
Run Code Online (Sandbox Code Playgroud)

son*_*yao 7

重点是名称查找,它发生在重载解析之前。

当名称foo在 namespace 中找到时NS,名称查找停止,不会检查进一步的范围,foo根本不会找到全局。那么在重载决议中只有一个候选者,并且int可以float隐式转换为,然后NS::foo(float)最后被调用。

(强调我的)

名称查找按如下所述检查作用域,直到找到至少一个任何类型的声明,此时查找停止并且不再检查其他作用域