【问题标题】:Why doesn't a using directive affect ADL?为什么 using 指令不影响 ADL?
【发布时间】:2015-02-17 03:22:42
【问题描述】:

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

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==

我怀疑原因与 using directive 应该使符号看起来像是在全局命名空间 :: 中的事实有关(因为这是命名空间alleqns)。但如果真的是这样,那::ns::operator==为什么会找到函数呢?

更一般地说,我试图在库中提供一些有用的operator==(和相关)重载,但如果人们不想要它们,我不会强迫他们使用这些定义。我希望允许人们根据他们是否将专用的运算符命名空间导入到他们自己的命名空间来启用或不启用他们的类型的 operator== (和相关的其他运算符)。现在看起来人们可能不得不编写大量使用 declarations (我可以用宏来简化它,但是很糟糕)。

【问题讨论】:

  • 听起来你正在尝试重新发明std::rel_ops,这通常被视为失败的实验
  • @JonathanWakely 为什么失败了?你能给我参考一些解释问题的文章吗?
  • @JonathanWakely 非常感谢!

标签: c++ namespaces argument-dependent-lookup


【解决方案1】:

我怀疑原因与 using directive 应该使符号看起来像是在全局命名空间 :: 中的事实有关(因为这是命名空间alleqns)。

确实如此,但仅适用于非限定查找,而不是依赖于参数的查找:

7.3.4 [namespace.udir]:

  1. using-directive 指定指定命名空间中的名称可以在 using-directive 出现在 using-directive 之后的范围内使用。在非限定名称查找 (3.4.1) 期间,名称看起来好像它们是在最近的封闭命名空间中声明的,其中包含 using-directive 和指定命名空间。

由于这仅适用于非限定名称查找,因此只有在从封闭命名空间内执行名称查找时才真正有帮助,当名称查找“向外”查找封闭命名空间时。它无助于从命名空间之外找到不合格的名称(ADL 就是这样做的)。

下一段说:

  1. using 指令不会将任何成员添加到它出现的声明区域。

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

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

3.4.2 [basic.lookup.argdep]

  1. 在考虑关联命名空间时,查找与将关联命名空间用作限定符 (3.4.3.2) 时执行的查找相同,除了:
    — 相关命名空间中的任何 using 指令都将被忽略。

【讨论】:

    猜你喜欢
    • 2014-04-16
    • 2014-10-12
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多