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

C++ 具有父命名空间的嵌套命名空间中的重载解析,c++,overload-resolution,name-lookup,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() { fo

我认为在嵌套的名称空间中,父(或全局)名称空间的任何部分都会被同等地考虑用于重载解析,但这个示例似乎显示了不同的情况

这很好:

#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();
}
foo(0)
的调用现在调用
foo(float)

我已经搜索了很多其他类似的页面,以找到解释这一点的规则,但我似乎没有找到它。有人能解释一下导致这种情况的众多复杂重载解析规则中的哪一条,还是其他原因

编辑
我刚刚发现这更奇怪。即使名称空间中的
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();
}
#包括
voidfoo(int){std::cout重点是,这发生在重载解析之前

当名称
foo
在命名空间
NS
中找到时,名称查找停止,不再检查进一步的作用域,将根本找不到全局
foo
。然后重载解析中只有一个候选项,
int
可以隐式转换为
float
,然后
NS::foo(float)
最终被调用

(强调矿山)

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


你能告诉我这部分是怎么说的吗?@Baruch补充道。你认为这很奇怪吗?你还没有考虑过其他选择。如果总是从所有可见的东西中形成一个重载集,那么即使稍微修改你的程序也是不可能的。想象一下,你为一些实用程序添加了一个新的头,但是其他未经调用的函数在文件中,工作方式突然发生了变化!这仅仅是因为新的头文件在重载解析中包含了更好的匹配项。
#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();
}