ADL
編程用語
徠ADL,參數相關查找,也稱作為Koenig查找(以Andrew Koenig的名字命名,有興趣可以看Scott Meyer的文章The Most Important C++ People...Ever),是指在編譯器對無限定域的函數調用進行名字查找時,所應用的一種查找規則。
C++中,由於引入了名字空間和類域,函數所在域就由原來的全局域變成如下幾個作用域。
(1)類域(函數作為某個類的成員函數(靜態或非靜態))
(2)名字空間域
(3)全局域
上面的函數調用,第一個f就是無限定域的函數調用,第二個則限定了在名字空間N裡面,也是說使用了完全限定名。而Koenig查找,它的規則就是當編譯器對無限定域的函數調用進行名字查找時,除了當前名字空間域以外,也會把函數參數類型所處的名字空間加入查找的範圍。
考察如下代碼。
我們通常都會寫如上的代碼,使用operator<<列印對象的狀態,但是ostream& operator<<(ostream& out, const KoenigArg& kArg)的定義是處於名字空間Koenig,為什麼編譯器在解析main函數(全局域)裡面的operator<<調用時,它能夠正確定位到Koenig名字空間裡面的operator<<?這是因為根據Koenig查找規則,編譯器需要把參數類型KoenigArg所在的名字空間Koenig也加入對operator<<調用的名字查找範圍中。
如果沒有Koenig查找規則,我們就無法直接寫cout<
很顯然,你的模版代碼根本無法確認T是來自那個名字空間,直到編譯器對模版實例化(print(karg); 被調用)。
對徠Koenig查找規則的一個異議是,由於Koenig查找規則的存在,處於某個名字空間的函數調用的重載決議會受到另外一個名字空間的自由函數所影響,僅僅是由於它使用了另外一個名字空間的類型作為參數。在這樣的規則下,名字空間看起來不像我們一般所想象的那樣是完全封閉和獨立的。
我們應該怎麼解釋這樣的異議呢?這樣隱諱的影響或者依賴性是合理的嗎?Herb認為,如果我們把另外一個名字空間的自由函數(非類成員函數)也看作是它所涉及的類型的介面的一部分,很顯然,它應該參與這樣的重載決議,這樣的跨越名字空間的影響是合理的。從而導出了Herb在傳統類定義之上的一個更詳細和完整的解釋(請參考Exceptional C++, Item 32)。
關於Koenig查找,我們該說的都說了嗎?其實未然,之前所描述的只是Koenig查找一般可能發生的狀況,當Koenig查找規則和C++原來的Ordinal Lookup(OL,順序查找規則)混合在一起的時候,它們之間的組合所產生的狀況要比之前的例子複雜的多。
目錄