Mar*_* Ba 6 c++ namespaces using global-namespace argument-dependent-lookup
诸如启用std类型输出之类的示例解释了如何使用ADL来“注入”某个函数/运算符,具体取决于 fn/op 应用到的类型。
我想知道 ADL 是否完全适用于全局命名空间,也就是说,using在全局命名空间范围内声明(或通过 提供)的类型是否使 ADL在全局命名空间中寻找匹配的函数?
具体来说,这些是等价的。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;
}
Run Code Online (Sandbox Code Playgroud)
写的。不需要 ADL 的全局命名空间范围:(在现已删除的答案后更新)
这种非限定调用的效果是进行非限定名称查找,因此编译器会搜索名称
operator<<。开始从词法位置在operator<<通话中找到“向上”(包括全局命名空间,顺便说一句)在当前的命名空间开始(...)以及所有包含该命名空间的命名空间和- ...
嗯。矿。请注意如何将外部命名空间描述为仅被视为“...来自词法位置...”。他继续:
...并且 - 作为第二条路线 - 它执行此查找的第二阶段,编译器在此调用中出现的参数类型的所谓关联命名空间中进行搜索。
在呈现的示例中,搜索的第一阶段失败,因为在
#include <iterator>存在的点上,operator<<在任何命名空间中都没有这些参数类型的对应项。请注意,您的声明operator<<是在某些库标头中 调用 of发生的点之后按词法提供的operator<<。搜索的第二阶段也将考虑到位置 跟踪实际的函数调用,但仅限于相关的命名空间。
大胆的强调。矿。所以在我看来,ADL 适用于全局命名空间是相关的。当然,我很容易误解了一些东西。
注意:这可能是标准的一种情况,只是没有以一种或另一种方式明确提及它,因为全局 NS 就像任何其他命名空间一样——但也可能不是,我对标准的了解非常有限。
完全忘记我最初的答案,这完全是错误的。
\n\n根据 C++11 标准,ADL 上的 \xc2\xa73.4.2 (强调我的):
\n\n\n\n\n当函数调用 (5.2.2) 中的后缀表达式是非限定 ID 时,在通常的非限定查找过程中不考虑其他命名空间可能会搜索其他命名空间,并且在这些命名空间中,\n 命名空间-scope 友元函数声明 (11.3) 不可见\n 可能会被发现。
\n
简而言之,由于不合格的查找将始终在全局命名空间中搜索,因此ADL永远不会应用于全局命名空间。
\n