为什么使用"使用指令"时 ADL 不起作用?

Why is the ADL not working when `using directive` is used?

本文关键字:quot 不起作用 ADL 指令 为什么      更新时间:2023-10-16

这是一个类似的问题,但在这个问题中它有效,但是,它在以下情况下失败,为什么?

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,并且永远不会在namespace B中找到void k(const test&)

但是,我认为ADL 应该在这种情况下工作,因为上面的代码不属于以下情况:

引自CPPREF

首先,如果通常的非限定查找生成的查找集包含以下任何内容,则不考虑依赖于参数的查找:
1)类成员的声明2)块范围内的函数声明(不是使用声明)3)任何不是函数或函数模板的

声明(例如,函数对象或名称与函数名称冲突的另一个变量)正在抬头)

更准确地说,这里using namespace A没有引入任何声明:
引用自cppref

using-

指令不会向它所在的声明性区域添加任何名称(与 using-声明不同),因此不会阻止声明相同的名称。

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

  • 正常非限定查找
  • 阿德勒

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

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

在您的代码中,正常的非限定查找确实会找到A::k如上一个问题中所述。因此,此代码不会发生 ADL。

using-指令指定指定命名空间中的名称可以在 using-指令之后出现 using-指令的作用域中使用。在非限定名称查找 (6.4.1) 期间,名称看起来就像是在最近的封闭命名空间中声明的,该命名空间同时包含 using-指令和指定的命名空间。

因此,非限定名称查找将找到 A::k,这就是错误的原因。