2017-08-01 48 views
3

考慮這個樣品中http://en.cppreference.com/w/cpp/language/adl描述:C++普通查找VS參數依賴查找

namespace A { 
     struct X; 
     struct Y; 
     void f(int); 
     void g(X); 
} 

namespace B { 
    void f(int i) { 
     f(i); // calls B::f (endless recursion) 
    } 
    void g(A::X x) { 
     g(x); // Error: ambiguous between B::g (ordinary lookup) 
       //  and A::g (argument-dependent lookup) 
    } 
    void h(A::Y y) { 
     h(y); // calls B::h (endless recursion): ADL examines the A namespace 
       // but finds no A::h, so only B::h from ordinary lookup is used 
    } 
} 

我很奇怪,爲什麼不確定性出現,因爲ADL規則沒有考慮到如果

「查找由通常的不合格查找產生的集合包含以下任何一個「。

這裏B ::克可通過如在http://en.cppreference.com/w/cpp/language/unqualified_lookup感謝解釋規則

對於在函數的定義中使用的名稱,或者在其主體或作爲其一部分不合格查找中找到默認參數,其中函數是用戶聲明或全局名稱空間的成員,在使用名稱之前搜索使用名稱的塊,然後在該塊的開始之前搜索封閉塊等,直到到達作爲功能體的塊。然後在該函數的聲明的名稱空間中搜索,直到使用的名稱,然後封閉命名空間的函數的定義(不一定是報關)等

然後我的問題是,爲什麼ADL認爲規則在這種情況下?

+0

你能詳細說明爲什麼你認爲它不應該被考慮在內嗎? – cpplearner

+0

首先,如果由通常的非限定查找產生的查找集包含以下任何一項,則不考慮依賴於參數的查找: – FlashMcQueen

+0

1)類成員的聲明 2)塊範圍的函數聲明(這不是使用聲明) 3)任何不是函數或函數模板的聲明(例如,函數對象或其名稱與正在查找的函數的名稱相沖突的變量) – FlashMcQueen

回答

1

爲什麼在這種情況下會考慮ADL(參數相關查找)規則?

因爲在關聯的命名空間中可能會有更好的匹配。例如:

void f(void*); 

namespace A { 
struct X; 
void f(X*); 
} 

int main() { 
    A::X* x = 0; 
    f(x); // A::f is the best match. 
} 

這種機制通常用於swap function

std::swap可以專門命名空間std爲用戶定義的類型,但是,這種特例並不由ADL實測值(命名空間std不用戶定義類型的關聯名稱空間)。 使用戶定義類型可交換的預期方式是在與類型相同的名稱空間中提供非成員函數交換:有關詳細信息,請參閱可交換。

任何左值或這種類型的右值可以與任何左值或一些其它類型的右值被交換,在其中兩個std::swap和用戶定義的swap() s爲可見的環境中使用不合格的函數調用swap()

+0

好的,謝謝你的好例子。 – FlashMcQueen

6

完整報價是

首先,參數相關的查找不被認爲是如果通過通常的不合格查找產生的查找組包含任何以下的:

  1. 的聲明類成員
  2. 塊範圍內的函數聲明(不是使用聲明)
  3. 任何聲明t帽子不是功能或功能模板(例如一個函數對象或其他變量,其名稱衝突與功能的多數民衆贊成正在查找的名稱)

這意思是,只有當不合格查找產生上述三種結果之一是ADL被忽略。由於我們沒有處理類成員,因此該函數是在名稱空間範圍而不是塊範圍中聲明的,我們只能找到繼續使用ADL的函數。

+0

那麼在塊作用域聲明一個函數意味着什麼(聲明在當前作用域內?) – FlashMcQueen

+0

@FlashMcQueen它是一個在[block作用域]聲明的函數(http://en.cppreference.com/w/CPP /語言/範圍#Block_scope) – NathanOliver