argument-dependent lookup或Koening lookup法则
当我们给函数传递一个类类型的对象时,首先会在常规的作用域查找,其次在实参类所属的命名空间查找。
查找顺序如下:
1. 先在本作用域内查找;
2. 在实参的命名空间 和 全局作用域中 同时查找;
当我们给函数传递一个类类型的对象时,首先会在常规的作用域查找,其次在实参类所属的命名空间查找。
查找顺序如下:
1. 先在本作用域内查找;
2. 在实参的命名空间 和 全局作用域中 同时查找;
这一规则也叫做argument-dependent lookup或Koening lookup法则。这一规则对传递类的引用或指针的调用同样有效。如果名称后面的括号里面有一个或多个实参表达式,那么ADL将会查找这些实参直接相关的所有namespace和class。其中,类包括直接基类和间接基类。Andrew Koenig首次提出了ADL,这也是为什么ADL有时也称为koenig查找的原因。最初ADL引入的动机只是为了方便编写a+b,其中a和b至少有一个是用户自定义类型。如果没有ADL,则就要写为N::operator+(a,b)。
下面我们用程序来验证一下:
#include <iostream>
using std::cout;
using std::endl;
namespace X {
void f(int) {
cout << "namespace X void f(int)" << endl;
}
}
namespace N {
using namespace X;
enum E{ e1 };
void f(E) {
cout << "N::f(N::E) is called!!!" << endl;
}
}
void f(N::E) {
cout << "::f(N::E) is called!!!" << endl;
}
int main() {
::f(N::e1);
f(N::e1); //error: call of overloaded 'f(N::E)' is ambiguous
return 0;
}
修改主函数代码为:
int main() {
void f(N::E);
::f(N::e1);
f(N::e1);
return 0;
}
输出:
::f(N::E) is called!!!
::f(N::E) is called!!!
或
int main() {
using N::f;
::f(N::e1);
f(N::e1);
return 0;
}
输出:
::f(N::E) is called!!!
N::f(N::E) is called!!!