7

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

我想知道 ADL 是否完全适用于全局命名空间,也就是说,在全局命名空间范围内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 描述了一个 ADL问题:

这个不合格的调用具有发生不合格名称查找的效果,因此,编译器会搜索名称operator<<。从在 当前命名空间和包含该命名空间的所有命名空间(包括全局命名空间,顺便operator<<一句)和 - ...

强调。矿。注意外部命名空间是如何被描述为只被认为是“......来自词汇位置......”。他继续:

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

在给出的示例中,搜索的第一阶段失败,因为在#include <iterator>存在的点上,在任何命名空间中都没有operator<<这些参数类型的对应关系。请注意,您的声明operator<<是在某些库头文件中某处发生 调用的点之后提供的。搜索的第二阶段还将考虑 实际函数调用之后的位置,但仅限于关联的命名空间内。operator<<

大胆的强调。矿。所以在我看来,ADL 适用于全局命名空间是相关的。当然,我很容易误解了一些东西。


注意:这可能是标准没有明确提及它的一种情况,因为全局 NS 就像任何其他命名空间一样——同样可能不是,我对标准的了解非常有限。

4

1 回答 1

4

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

根据 C++11 标准,关于 ADL 的第 3.4.2 节(强调我的):

当函数调用 (5.2.2) 中的后缀表达式是非限定 ID 时,可能会搜索在通常的非限定查找(3.4.1) 期间未考虑的其他命名空间,并且在这些命名空间中,命名空间范围的友元函数声明 ( 11.3) 可能会发现其他不可见的。

所以简而言之,由于不合格的查找总是在全局命名空间中搜索,ADL永远不会应用于全局命名空间

于 2014-08-05T07:53:01.233 回答