为什么using指令不影响ADL? [英] Why doesn't a using directive affect ADL?

查看:85
本文介绍了为什么using指令不影响ADL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解为什么以下代码无法编译:

I am trying to understand why the following code does not compile:

namespace ns {
  struct S {};
}

namespace alleq {
  inline bool
  operator==(const ns::S &, const ns::S &)
  {
    return true;
  }
}

namespace ns {
  using namespace alleq;
  // using alleq::operator==; // Works if you uncomment this
}

ns::S a;

void
f()
{
  ::ns::operator==(a, a); // OK
  a == a;                 // Error: no match for 'operator=='
}

函数f的第一行确实可以编译,这使我相信名称空间ns包含函数operator==.但是,当我比较两个ns::S类型的值时,找不到此operator==函数.相比之下,using声明确实可以按预期工作,并且允许f的第二行通过ADL查找ns::operator==.

The first line of function f does compile, which makes me believe that namespace ns contains a function operator==. However, when I compare two values of type ns::S, this operator== function is not found. By contrast, a using declaration does work as expected, and allow the second line of f to find ns::operator== by ADL.

我怀疑原因与使用指令应该使该符号看起来像在全局命名空间::中一样(因为这是该符号的共同祖先)命名空间alleqns).但是,如果确实如此,为什么::ns::operator==会找到该函数?

I suspect the reason has to do with the fact that a using directive is supposed to make the symbol appear as if it is in the global namespace :: (because that is the common ancestor of namespaces alleq and ns). But if that were really the case, then why would ::ns::operator== find the function?

更笼统地说,我正在尝试在库中提供一些有用的operator==(及相关)重载,但并不想强迫人们使用不需要的定义.我希望允许人们根据是否将专用的运算符命名空间导入自己的命名空间来启用或禁用operator ==(以及其他相关运算符).现在看来,人们可能不得不编写大量使用声明的程序(我可以使用宏来简化它,但是很糟糕).

More generally, I'm trying to provide some useful operator== (and related) overloads in a library, but not force people to use the definitions if they don't want them. I was hoping to allow people to enable or not enable operator== (and related other operators) on their types based on whether they import a dedicated operator namespace into their own namespace. Now it looks like people may have to write a host of using declarations (which I could simplify with a macro, but yuck).

推荐答案

我怀疑原因与使用指令应该使该符号看起来像在全局命名空间::中一样(因为这是该符号的共同祖先)命名空间alleqns).

I suspect the reason has to do with the fact that a using directive is supposed to make the symbol appear as if it is in the global namespace :: (because that is the common ancestor of namespaces alleq and ns).

这是正确的,但仅用于不合格的查找,而不是与参数相关的查找:

That's sort of true, but only for unqualified lookup, not argument-dependent lookup:

7.3.4 [namespace.udir]:

7.3.4 [namespace.udir]:

  1. using-directive 指定可以在 using-directive之后出现 using-directive 的范围内使用命名空间中的名称. .在进行非限定名称查找(3.4.1)期间,这些名称看起来好像是在包含 using-directive 和指定名称空间的最近封闭式名称空间中声明的一样.
  1. A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup (3.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace.

由于这仅适用于不合格的名称查找,因此只有在从名称空间中查找名称向外"时,才从封闭的名称空间中执行名称查找时真正有用.它无助于从命名空间之外查找不合格的名称(这是ADL的作用).

Since that only applies to unqualified name lookup, it only really helps when performing name lookup from within the enclosing namespace, when name lookup looks "outwards" into enclosing namespaces. It doesn't help find unqualified names from outside the namespace (which is what ADL does).

下一段指出:

  1. using伪指令不会将任何成员添加到它所在的声明性区域中.

即using指令使名称在作用域中可见,但不会在该作用域中添加新的声明.

i.e. A using directive makes names visible in a scope, but does not add new declarations to the scope.

您看到的行为的原因仅仅是该标准说ADL会忽略使用指令:

The reason for the behaviour you see is simply that the standard says ADL ignores using directives:

3.4.2 [basic.lookup.argdep]

3.4.2 [basic.lookup.argdep]

  1. 考虑关联的名称空间时,查找与将关联的名称空间用作限定符(3.4.3.2)时执行的查找相同,不同之处在于:
    —关联名称空间中的所有using指令都将被忽略.
  1. When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier (3.4.3.2) except that:
    — Any using-directives in the associated namespace are ignored.

这篇关于为什么using指令不影响ADL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆