【问题标题】:Does ADL work for the global namespace?ADL 是否适用于全局命名空间?
【发布时间】:2014-09-27 19:04:21
【问题描述】:

Examples such as 启用 std 类型的输出解释了如何使用 ADL 来“注入”某个函数/运算符,具体取决于应用 fn/op 的类型。

我想知道 ADL 是否完全适用于全局命名空间,也就是说,在 global namespace scope 声明的类型(或通过 using 提供)是否使 ADL 在全局命名空间中寻找匹配的函数?

具体来说,这些是等价的吗?日常生活?:

// 1 - at global namespace scope
struct GlobalType {};

template< class Ch, class Tr>
std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& os, GlobalType const& x)
{
    os << ...;
    return os;
} 

// 2 - within namespace
namespace ecaps {

    struct EcapsType {};

    template< class Ch, class Tr>
    std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& os, EcapsType const& x)
    {
        os << ...;
        return os;
    } 

}

// 3 - Type brought to global NS via using, function at global scope
namespace other {
    struct OtherType {};    
}

using other::OtherType;

template< class Ch, class Tr>
std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& os, OtherType const& x)
{
    os << ...;
    return os;
} 

写。不需要 ADL 的全局命名空间范围:(在现已删除的答案后更新)

一个Daniel Krügler of Committee fame describes an ADL problem 这样:

这个不合格的调用具有不合格名称查找的效果 发生,因此,编译器搜索 名称operator&lt;&lt;从词法位置开始 operator&lt;&lt; 调用从当前命名空间开始“向上” (...) 包含该命名空间的命名空间(包括全局 命名空间,顺便说一句。)和 - ...

强调。矿。请注意外部命名空间是如何被描述为仅被视为“... 来自词法位置 ...”。他继续说:

... 并且 - 作为第二条路线 - 它执行第二阶段 lookup 编译器在所谓的关联命名空间中搜索 此调用中出现的参数类型。

在给出的示例中,搜索的第一阶段失败,因为 在#include &lt;iterator&gt; 存在的地方,没有 任何命名空间中的这些参数类型对应的operator&lt;&lt;。 请注意,您的 operator&lt;&lt; 声明是按词法提供的之后 operator&lt;&lt; 的调用发生在某些地方 库标题。 搜索的第二阶段也将 考虑位置 跟随实际的函数调用,但仅限于相关的命名空间内。

粗体字。矿。因此,在我看来,ADL 适用于全局命名空间 相关。当然,我很容易误解了一些东西。


注意:这可能是标准的一个例子,只是没有明确地以一种或另一种方式提及它,因为全局 NS 就像任何其他命名空间一样——那么它可能不会,据我所知标准非常有限。

【问题讨论】:

  • 不需要ADL,因为全局函数已经可用。
  • @BЈовић - 查看正在进行的编辑
  • 我不明白到底是什么问题。您能否创建一个示例,其中不考虑全局命名空间中的函数?

标签: c++ namespaces using argument-dependent-lookup global-namespace


【解决方案1】:

完全忘记我最初的回答,这是完全错误的。

来自 C++11 标准,关于 ADL 的第 3.4.2 节(重点是我的):

当函数调用 (5.2.2) 中的后缀表达式是 unqualified-id,其他命名空间平时不考虑 可能会搜索不合格的查找 (3.4.1),并且在这些命名空间中, 命名空间范围的友元函数声明(11.3),否则 可以找到可见的。

简而言之,由于非限定查找将始终在全局命名空间中搜索,ADL 将永远应用于全局命名空间

【讨论】:

  • @MartinBa 在 Daniel 的示例中,命名空间 std 不会在查找的第二阶段(即 ADL 期间)被考虑,它只会然后考虑,因为它不是调用相关函数的站点的封闭命名空间。
  • N3337 / 14.6.4.2 : "对于使用关联命名空间 (3.4.2) 的查找部分,仅在 模板定义上下文 或模板中找到函数声明找到实例化上下文。” - 所以我说你对 3.4.2 的解释是错误的。
猜你喜欢
  • 2013-06-18
  • 2016-12-01
  • 1970-01-01
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多