重载决议:这怎么不模糊?

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.非限定查找会考虑本地块范围,找到匹配项,并在考虑更广泛的类范围之前停止.由于没有函数参数,因此没有依赖于参数的查找,因此不会考虑其他范围.


Rei*_*ica 7

@ 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声明引入.