ADL(Koenig) 查找
ADL ,參數(shù)相關(guān)查找,也稱作為 Koenig 查找(以 Andrew Koenig 的名字命名),是指在編譯器對無限定域的函數(shù)調(diào)用進(jìn)行名字查找時(shí),所應(yīng)用的一種查找規(guī)則。
首先來看一個(gè)函數(shù)所在的域的分類:
1 :類域(函數(shù)作為某個(gè)類的成員函數(shù)(靜態(tài)或非靜態(tài)))
2 :名字空間域
3 :全局域
而 Koenig 查找,它的規(guī)則就是當(dāng)編譯器對無限定域的函數(shù)調(diào)用進(jìn)行名字查找時(shí),除了當(dāng)前名字空間域以外,也會把函數(shù)參數(shù)類型所處的名字空間 加入查找的范圍。
ADL 就是為了確保使用類型 X 的對象 x 時(shí)能夠像使用 X 的成員函數(shù)一樣簡單 (ensure that code that uses an object x of type X can use its nonmember function interface as easily as it can use member functions) 。
根據(jù) ADL 規(guī)則,如果非成員函數(shù)想和類型一起被使用,應(yīng)該將它們置于同一個(gè)名字空間中。換句話說,和類型 X 放在同一名字空間下的非成員函數(shù),也是 X 接口的一部分。 ( 常見的有 <<or>> 操作符 )
示例:
#include <iostream>
//class N // 類域
//{
//public :
// enum E {e1};
// void f(E)
// {
// std::cout << "N::f(N::E) called\n";
// }
//};
namespace N{ // 名字空間域
enum E {e1};
void f(E){
std::cout << "N::f(N::E) called\n";
}
}
void f(int)
{
std::cout << " ::f(int) called\n";
}
int main()
{
::f(N::e1); // 受限函數(shù),禁用 ADL // 輸出 ::f(int) called
f(N::e1); // 普通查找到 f();
return 0;
}
上述例子,如果 N 為 class ,輸出為: ::f(int) called ;如果 N 為名字空間,輸出: N::f(N::E) called 。
也就是說 ADL 僅會將參數(shù)所在的名字空間中的函數(shù)名字加入查找范圍。
調(diào)用函數(shù)時(shí),顯式地限定名字空間將禁用 ADL 查找 ,加快解析過程。
Argument Dependent Lookup (ADL)解析
ADL,參數(shù)相關(guān)查找,也稱作為Koenig查找(以Andrew Koenig的名字命名,有興趣可以看Scott Meyer的文章The Most Important C++ People...Ever),是指在編譯器對無限定域的函數(shù)調(diào)用進(jìn)行名字查找時(shí),所應(yīng)用的一種查找規(guī)則。


Koenig Lookup(simplified): If you supply a function argument of class type (here x, of type A::X), then to look up the correct function name the compiler considers matching names in the namespace (here A) containing the argument's type.



































我們通常都會寫如上的代碼,使用operator<<打印對象的狀態(tài),但是ostream& operator<<(ostream& out, const KoenigArg& kArg) 的定義是處于名字空間Koenig,為什么編譯器在解析main函數(shù)(全局域)里面的operator<<調(diào)用時(shí),它能夠正確定位到Koenig名字空間里面的operator<<?這是因?yàn)楦鶕?jù)Koenig查找規(guī)則,編譯器需要把參數(shù)類型KoenigArg所在的名字空間Koenig也加入對operator<<調(diào)用的名字查找范圍中。
如果沒有Koenig查找規(guī)則,我們就無法直接寫cout<<karg;,而是需要寫類似Koenig::operator<<(std::cout, karg); 這樣的代碼(使用完全限定名)。嗯,即不直觀也不方便是嗎?更重要的是如果我們寫的是模版代碼,在模版參數(shù)還沒有實(shí)例化之前,我們根本就不知道參數(shù)所處的名字空間,比如:






A class describes a set of data, along with the functions that operate on that data.
are logically part of X, because they form part of the interface of X.