具有父命名空间的嵌套命名空间中的重载解析
Overload resolution in nested namespace with parent namespace
我认为在嵌套的命名空间中,任何属于父(或全局)命名空间的部分都被同等地考虑用于重载解析,但这个例子似乎不是这样。
这很好用:
#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(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();
}
对 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();
}
重点是 name lookup,它发生在重载解析之前。
当在命名空间 NS
中找到名称 foo
时,名称查找将停止,不会检查进一步的范围,全局 foo
将不会在全部。然后在重载决策中只有一个候选者,并且 int
可以隐式转换为 float
,然后 NS::foo(float)
最后被调用。
(强调我的)
name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.
我认为在嵌套的命名空间中,任何属于父(或全局)命名空间的部分都被同等地考虑用于重载解析,但这个例子似乎不是这样。
这很好用:
#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(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();
}
对 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();
}
重点是 name lookup,它发生在重载解析之前。
当在命名空间 NS
中找到名称 foo
时,名称查找将停止,不会检查进一步的范围,全局 foo
将不会在全部。然后在重载决策中只有一个候选者,并且 int
可以隐式转换为 float
,然后 NS::foo(float)
最后被调用。
(强调我的)
name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.