类(模板)成员函数体内部的ADL查找

ADL lookup inside a class (template) member function body

本文关键字:内部 ADL 查找 函数体 成员 模板      更新时间:2023-10-16
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{});
}

激活#1行中的ADL查找与一样简单

{
using ::f;
f(v);
}

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

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

  • (3.1)类成员的声明,或
  • (3.2)不是using声明的块作用域函数声明,或者
  • (3.3)既不是函数也不是函数模板的声明

则Y为空。[…]

因此,由于通过非ADL查找找到的对f的调用将找到作为类成员的A::f,因此通过ADL查找发现的重载将被丢弃。

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

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

关于不合格名称查找的第一段:

在〔basic.lookup.uqual〕中列出的所有情况下,作用域都是按每个中列出的顺序搜索声明各自类别;一旦声明为名称找到。

特别是

对于类X的成员,在成员函数体中使用的名称[…]如下成员的声明符id,应在以下方式:

  • 在使用它的块中或在封闭中使用之前块([stmt.block])或

  • 应为X类成员或成员X([class.member.lookup])的基类,或者。。。

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