2013-01-05 40 views
6

我無法理解參數相關(Koenig)查找背後的規則。基於參數的查找 - 何時完成,搜索什麼,以及如何強制(或阻止)它?

考慮下面的代碼:

#include <iostream> 

using namespace std; 

namespace adl 
{ 
    struct Test { }; 
    void foo1(Test const &) { cout << "ADL used (foo1)" << endl; } 
    void foo2(Test const &) { cout << "ADL used (foo2)" << endl; } 
    void foo3(Test const &) { cout << "ADL used (foo3)" << endl; } 
} 

struct foo1 
{ 
    foo1() { } 

    template<class T> 
    foo1(T const &) { cout << "ADL not used (foo1)" << endl; } 

    template<class T> 
    void operator()(T const &) const { cout << "ADL not used (foo3)" << endl; } 
}; 

template<class T> void foo2(T const &) 
{ cout << "ADL not used (foo2)" << endl; } 

int main() 
{ 
    adl::Test t; 
    foo1 foo3; 
    (foo1(t)); 
    (foo2(t)); 
    (foo3(t)); 
} 

它的輸出是:

ADL不使用(foo1
ADL使用(foo2
ADL不使用(foo3

我e他們認爲所有人都使用ADL,但我很驚訝,只有他們中的一些人做到了。

什麼是(潛在的血管,我知道)細節背後的ADL規則?
我很理解這個概念,但細節就是我遇到的問題。

搜索哪些範圍,何時搜索以及何時不搜索?

是它在所有可能告訴ADL是否無需通過所有#include「d文件,以尋找代碼定行之前使用?我期望仿函數和函數在掩蓋ADL方面表現出相同的行爲,但顯然他們不行。

有沒有辦法通過force ADL在沒有自動完成的情況下(比如上面的情況)並且你不知道類的命名空間(例如在模板中)?

+1

-1這個問題太廣泛了,代碼示例真的很糟糕(帶有誤導性的名字等)。 –

+1

我不明白。你爲什麼要試驗'(foo3(t));'?沒有名爲'foo3'的函數。所以ADL不會進入畫面。 'foo3'將被視爲對象,毫無疑問,因爲這就是它的意思(這意味着它將毫無疑問地調用'operator()')!這只是您在示例中使用的誤導性名稱。 – Nawaz

+0

@ Cheersandhth.-Alf:但是對'(foo3(t))'沒有混淆;'。這只是他爲變量使用了誤導性的名字! – Nawaz

回答

5

你的問題不是真正的依賴於參數的查找。首先,參數依賴查找只有在對函數進行不合格的查詢時纔可能進入圖片。當致電foo1(t)foo1是一個類型,並且它的模板化構造函數被調用。同樣,foo3(t)是合格的查找,因爲foo3是一個對象,函數調用操作符在對象的類foo1中查找。其中參數查找進入圖片的唯一地方被調用foo2(t)其中查找發現候選人:

  1. ::foo2<adl::Test>(adl::Test const&)
  2. ::adl::foo2(adl::Test const&)

這兩個函數切換到過載分辨率並且由於這兩種功能都同樣與非模板功能獲勝相匹配。

你的問題實際上是三個問題:

  1. 名稱查找的血淋淋的細節過於寬泛,因此,這個問題是要寫入的文章,我忽略的請求。
  2. 第二個問題擴展到三個問題,只有一個似乎相關:
    1. 搜索了哪些範圍?在函數定義中查找非限定函數名稱時,規則取決於是否有任何名稱是從屬名稱。如果沒有這樣的名稱(即,在非模板代碼中或者在第一階段中可以確定名稱的模板代碼中),則名稱會在名稱空間和與其參數相關聯的名稱空間中查找。否則,名稱只能在關聯的名稱空間中查找。
  3. 參數相關的查找可以被強制嗎?如果存在至少一個參數,但是找到名稱,則始終爲非限定函數查找完成,否則可能會更好匹配。當然,你需要調用一個不合格的函數,否則它不會完成。
+0

仍試圖瞭解什麼使呼叫「不合格」。我認爲「不合格」意味着「沒有提及限定詞[即命名空間]」......但顯然情況並非如此,因爲這些都沒有提及命名空間?呼叫不合格是什麼意思? – Mehrdad

+0

當名稱被查找時,它首先命名該名稱,並在名稱被找到時停止。 'foo1'找到一個類型並查找構造函數以在類型的上下文中調用。由於在函數之前找到類型,因此不考慮其他名稱空間。類似地,對於被發現是對象類型的純文本中查找函數調用操作符的對象的'foo3'。對於'foo2',找到一個函數並且調用是不合格的,即搜索與參數相關的命名空間以增加過載集合。 –

+0

這是編譯器遵循的*過程*的一個很好的描述,但我仍然不明白「合格」是什麼意思。您似乎將資格定義爲「任何引發ADL的調用」,然後說ADL只針對非限定調用完成......按定義這是真實的,但無法幫助我理解符合調用的條件。但是,究竟是什麼使呼叫合格呢?我如何判斷一個給定的電話是否合格? – Mehrdad

相關問題