在类(模板)成员函数体内进行ADL查找

Per*_*-lk 3 c++ language-lawyer class-members argument-dependent-lookup c++17

struct B {};
struct C : B {};
void f(B){} // worse match than A::f<C>

struct A {
    template<class T>
    void f(T v) {
        f(v); // #1
    }
};

int main()
{
    A{}.f(C{});
}
Run Code Online (Sandbox Code Playgroud)

在线激活ADL查找#1非常简单

{
    using ::f;
    f(v);
}
Run Code Online (Sandbox Code Playgroud)

我认为在没有using指令的情况下使代码失败的规则是:

[basic.lookup.argdep]/3设X是非限定查找生成的查找集,让Y为参数相关查找生成的查找集(定义如下).如果X包含

  • (3.1)集体成员的声明,或
  • (3.2)不是使用声明的块范围函数声明,或
  • (3.3)既不是函数也不是函数模板的声明

那么Y是空的.[...]

因此,由于f非ADL查找找到的调用将找到A::f,这是一个类成员,ADL-lookup发现的重载将被丢弃.

哪个C++规则允许忽略3.1中的限制using声明,以使上面的代码编译?

我想我完全误解了必须应用规则[basic.lookup.argdep]/3的上下文,或者在理解名称查找过程中我可能有一个更大的隐藏漏洞.

Col*_*mbo 5

关于非限定名称查找的第一段:

在[basic.lookup.unqual]中列出的所有情况中,将按照每个相应类别中列出的顺序搜索范围; 一旦找到名称的声明,名称查找就会结束.

特别是,

对于类的成员,X在成员函数体[...]中使用的名称,在成员的declarator-id之后,应以下列方式之一声明:

对名称的本地(重新)声明进行优先级排序并隐藏所有外部声明.