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

标签 c++ language-lawyer argument-dependent-lookup name-lookup unqualified-name

[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 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.

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

因此,Y 是空的,这使得 XY 的并集只是 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/

相关文章:

c++ - 在 QMenuBar/QMenu 上捕获 keyPressEvent?

c++ - 分流码算法插入前缀实现中

c++ - 用逗号相互依赖初始化?

c++ - 这种模板函数重载的案例让我无法理解

c++ - 我应该在哪里为我的 std::pair 特化定义运算符 >>?

c++ - 如何在 C++ 中创建 vector 的 vector 映射?

c++ - 我可以使用 memcpy 写入多个相邻的标准布局子对象吗?

c++ - 自定义容器应该有免费的开始/结束功能吗?

c++ - 一般开始,加上 decltype 考虑本地 using-declaration

c++ - 未按描述收到事件通知