为什么使用“using 指令”时 ADL 不起作用?

2024-03-08

这是一个类似的问题 https://stackoverflow.com/questions/24384020/why-does-the-compiler-stops-the-name-lookup-on-overloads,但是在这个问题中它有效,但是在以下情况下它失败了,为什么?

namespace A
{
  int k;
}
namespace B
{
  class test{};
  void k(const test&){/*do something*/}
}

int main()
{
  using namespace A;
  k(B::test());//compile error
}  

错误信息是:“'A::k' 不能用作函数”(gcc 6.3.0)

也就是说,编译器不会尝试这样做ADL并且永远找不到void k(const test&) in namespace B

然而,我认为ADL 应该在这种情况下发挥作用因为上面的代码不属于以下情况:

引用自cppref http://en.cppreference.com/w/cpp/language/adl

首先,如果通常的非限定查找生成的查找集包含以下任何内容,则不考虑参数相关查找:
1) a 宣言班级成员的
2) a 宣言块作用域的函数(这不是 using 声明)
3)任何宣言这不是函数或函数模板(例如,函数对象或名称与正在查找的函数名称冲突的另一个变量)

更准确地说,这里using namespace A 不引入任何声明:
引用自cppref http://en.cppreference.com/w/cpp/language/namespace

using 指令不会将任何名称添加到它出现的声明区域(与 using 声明不同),因此不会阻止声明相同的名称。


函数调用的名称查找分为两部分:

  • 正常的不合格查找
  • ADL

根据 N4659 [basic.lookup.argdep]/3,首先发生正常的不合格查找;如果发现正常的不合格查找,则 ADL 阶段不会继续:

  • 类成员的声明,或
  • 不是 using 声明的块作用域函数声明,或者
  • 既不是函数也不是函数模板的声明。

在您的代码中,正常的非限定查找确实找到了A::k正如所讨论的你之前的问题 https://stackoverflow.com/questions/49312133/。所以这段代码不会发生 ADL。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么使用“using 指令”时 ADL 不起作用? 的相关文章

随机推荐