当基类在C++中具有交换函数时,为什么名称查找找不到std::swap?
我有我代码中内容的副本
#include <utility>
using namespace std;
class Parent
{
public:
void swap(Parent*);
};
class A : public Parent
{
public:
void handle();
};
void A::handle()
{
long x = 1;
long y = 2;
swap(x,y);
}
int main()
{
A v;
v.handle();
return 0;
}
错误日志:
main.cpp: In member function 'void A::handle()':
main.cpp:21:10: error: no matching function for call to 'A::swap(long int&, long int&)'
swap(x,y);
^
main.cpp:7:8: note: candidate: void Parent::swap(Parent*)
void swap(Parent*);
^
main.cpp:7:8: note: candidate expects 1 argument, 2 provided
据我了解,swap内部调用A::handle()将触发非限定查找,并且因为它将在作为函数的父类中找到交换名称,因此将调用依赖于参数的名称查找 (ADL)。为什么这里的 ADL 找不到std::swap并使用它?相反,它尝试调用父级的交换。
我在这里缺少什么?
平台/编译器:Red hat 6.7/ GNU 5.3.0
平台/编译器:Windows 10/visual studio 2015
回答
对于不合格的名称查找:
名称查找按如下所述检查作用域,直到找到至少一个任何类型的声明,此时查找停止并且不再检查其他作用域。
所以名称首先swap在类中检查,A没有找到,然后在类中检查,Parent找到了,然后名称查找停止。std::swap引入到全局范围内根本不会被发现。
和
为什么这里的 ADL 找不到
std::swap并使用它?
您将longs传递给swap,而ADL可以处理类类型,但不能处理基本类型。
- 对于基本类型的参数,关联的命名空间和类集为空
顺便说一句:在这种特殊情况下,即使您更改将std命名空间中定义的某些类类型传递给swapADL 也不会被考虑。
首先,如果通常的非限定查找生成的查找集包含以下任何一项,则不考虑参数相关查找:
- 类成员的声明
Parent::swap 是通过通常的非限定名称查找找到的类成员,ADL 仍然不会被考虑。
- @ShadyAtef `long` 不是 `std` 的成员,所以没有 ADL。ADL 适用于在同一命名空间中声明的类型和函数。