在我看来,在 [basic.lookup.argdep]/3 中的示例中,调用 g(parm, 1) 有两个候选函数

It seems to me that there are two candidate functions for the call g(parm, 1) in the example in [basic.lookup.argdep]/3

[basic.lookup.argdep]/3中的示例:

namespace NS {
    class T { };
    void f(T);
    void g(T, int);
}
NS::T parm;
void g(NS::T, float);
int main() {
    f(parm); // OK: calls NS::f
    extern void g(NS::T, float);
    g(parm, 1); // OK: calls g(NS::T, float)
}

对于调用 g(parm, 1) 我们在集合 X 中有全局范围内的声明 void g(NS::T, float);。 AFAICT,我们在集合 Y 中还有命名空间 NS 中的声明 void g(T, int);,类型为 [=17= 的参数 parm 的关联命名空间].因此,如果我没记错的话,这两个声明是重载决议的候选者。那么,与命名空间 NS 中的声明相比,全局范围中的声明是否更受青睐?为什么?我非常感谢引用标准中的一句话作为答案。

在那个部分,我们有:

Let X be the lookup set produced by unqualified lookup and let Y be the lookup set produced by argument dependent lookup (defined as follows). If X contains

  • a declaration of a class member, or
  • a block-scope function declaration that is not a using-declaration, or
  • a declaration that is neither a function nor a function template

then Y is empty.

非限定查找找到块作用域函数声明 - extern void g(NS::T, float)。不是全局范围的声明 ::g.

因此,Y 是空的,这使得 XY 的联合简单地只是 X,它只包含一个声明,这是一个可行的候选人。

如果该声明不存在,则非限定查找会找到 void g(NS::T, float),我们将继续执行 ADL,这会找到更好的匹配 N::g(T, int)