[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 中也有声明 void g(T, int);
在命名空间 NS
, 参数的关联命名空间 parm
类型 NS::T
.因此,如果我没记错的话,这两个声明是重载决议的候选者。那么,全局范围内的声明是否比命名空间NS
中的声明更受青睐? ?为什么?我非常感谢引用标准中的一句话作为答案。
最佳答案
在那个部分,我们有:
Let
X
be the lookup set produced by unqualified lookup and letY
be the lookup set produced by argument dependent lookup (defined as follows). IfX
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.
非限定查找找到 block 作用域函数声明 - extern void g(NS::T, float)
。不是全局范围内的声明 ::g
。
因此,Y
是空的,这使得 X
和 Y
的并集只是 X
,这只包含一个声明,这是一个可行的候选者。
如果该声明不存在,则非限定查找将找到 void g(NS::T, float)
并且我们将继续执行 ADL,这将找到 N: :g(T, int)
,这是一个更好的匹配。
关于c++ - 在我看来,[basic.lookup.argdep]/3 中的示例中有两个候选函数用于调用 g(parm, 1),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51680164/