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的上下文,或者在理解名称查找过程中我可能有一个更大的隐藏漏洞.
关于非限定名称查找的第一段:
在[basic.lookup.unqual]中列出的所有情况中,将按照每个相应类别中列出的顺序搜索范围; 一旦找到名称的声明,名称查找就会结束.
特别是,
对于类的成员,
X在成员函数体[...]中使用的名称,在成员的declarator-id之后,应以下列方式之一声明:
在使用它的块中或在封闭块([stmt.block])中使用之前,或者
应该是类的成员
X或者是X([class.member.lookup])的基类的成员,或者......
对名称的本地(重新)声明进行优先级排序并隐藏所有外部声明.