【发布时间】:2015-07-13 23:15:01
【问题描述】:
这个问题的灵感来自this one。考虑代码:
namespace ns {
template <typename T>
void swap(T& a, T& b) {
using namespace std;
swap(a, b);
}
}
经过 GCC 的一些测试,我发现 swap(a, b); 解析为
1) std::swap 如果 T 已重载 std::swap(例如,标准容器类型)
2) ns::swap 否则会导致无限递归。
因此,编译器似乎会首先尝试在命名空间ns 中找到匹配项。如果找到匹配项,则搜索结束。但是当 ADL 进来的时候就不是这样了,在这种情况下,std::swap 无论如何都找到了。解决过程似乎很复杂。
我想知道在上述上下文中解析函数调用swap(a, b) 的过程中的幕后细节。参考标准将不胜感激。
【问题讨论】:
-
请注意,
using namespace std;等使用指令的行为非常特殊;他们没有使用using std::swap等声明。 -
@dyp 对此深有感触 :-)
-
据我所知,这个 using 指令不会做任何事情。它使名称空间
std的名称可见,就好像它们在此处的全局名称空间中声明一样,但是全局名称空间中的名称swap对于ns::swap内的纯非限定查找是隐藏的,因为名称空间ns已经包含一个名称swap的成员。 -
所以,如果我理解正确,如果你把它改成使用 std::swap,我们会得到编译错误,因为编译器会同时看到 std::swap 和 ns::swap。
-
@AntonFrolov 这里涉及到两种名称查找机制:纯非限定查找和参数相关查找。纯非限定查找将在找到名称的下一个封闭范围内停止。使用
using std::swap;,我们告诉它在块范围内停止 - 将找不到ns::swap,它是封闭命名空间范围的成员。另一方面,依赖于参数的查找搜索与参数类型相关的所有范围。
标签: c++ language-lawyer function-calls overload-resolution argument-dependent-lookup