using-declaration 充当普通声明:它隐藏外部范围声明,但不抑制参数相关查找 (ADL)。
当你这样做时,using B::f
你基本上什么都没有改变。您只需B::f
在本地范围内重新声明,无论如何它已经可见。这并不妨碍 ADL 也能找到,这会在和A::f
之间产生歧义。A::f
B::f
如果这样做using A::f
,则 的本地声明会A::f
隐藏 的外部声明B::f
。所以B::f
不再可见,也不再通过不合格的名称查找找到。现在只A::f
找到了,这意味着不再有歧义。
无法抑制 ADL。由于您的案例中的参数是A::X
类型A::f
的,因此 ADL 将始终为 unqualified name 找到function f
。您不能将其“排除”在考虑之外。这意味着你不能B::f
在不产生歧义的情况下考虑。唯一的方法是使用限定名称。
正如@Richard Smith 在评论中正确指出的那样,可以抑制 ADL。ADL 仅在函数名本身用作函数调用中的后缀表达式时使用。以任何其他方式指定目标函数都会吓到 ADL。
例如,函数指针的初始化不受 ADL 约束
void g( A::X x )
{
void (*pf)(A::X) = &f;
pf(x);
}
在上面的例子B::f
中会被调用。甚至仅仅一对()
环绕函数名就足以抑制 ADL,即
void g( A::X x )
{
(f)(x);
}
已经足够让它调用了B::f
。