Bar*_*rry 3 c++ language-lawyer overload-resolution
假设我们有这个代码,从一个单独的问题复制:
namespace x
{
void f()
{
}
class C
{
void f()
{
using x::f;
f(); // <==
}
};
}
Run Code Online (Sandbox Code Playgroud)
f指示行上的名称明确指出x::f(至少根据gcc和clang).为什么在这种情况下更x::f喜欢x::C::f?两个名字都可见,这不应该是模棱两可的吗?
Mik*_*our 10
因为using声明x::f带入的范围f比范围窄C.非限定查找会考虑本地块范围,找到匹配项,并在考虑更广泛的类范围之前停止.由于没有函数参数,因此没有依赖于参数的查找,因此不会考虑其他范围.
@ Mike Seymour的回答是现场的; 这里是相关的标准引用(C++ 11,强调我的):
13.3.1.1.1/3:
在非限定函数调用中,名称不由
->或.运算符限定,并且具有更通用的primary-expression形式.在函数调用的上下文中查找名称,遵循函数调用中的名称查找的常规规则(3.4).该查找找到的函数声明构成候选函数集.由于名称查找的规则,候选函数集包括(1)完全由非成员函数或(2)完全由某些类的成员函数组成T....
3.4.1/1:
在3.4.1中列出的所有情况下,在每个相应类别中列出的顺序中搜索范围; 一旦找到名称的声明,名称查找就会结束.如果没有找到声明,该程序就是格式错误.
3.4.1/8
X在函数的declarator-id ... 之后的类的成员函数(9.3)的定义中使用的名称应以下列方式之一声明:
- 在用于使用它的块中或在封闭块(6.3)中使用之前,或
- 应是班级成员
X或是X(10.2)基类的成员,或- ...
从3.4.1/8开始,我们看到在使用它的块中的名称f(例如声明using x::f;)的声明早于f作为类的成员列出C.根据3.4.1/1,选择较早的一个,因此整个查找解析x::f为由using声明引入.