2017-03-07 79 views
7

綜觀boost::polygon的源代碼,我已經看到了以下主題的多種應用:調用函數命名空間中的無資質

#include <iostream> 

namespace B { 

struct A { 
    void foo() const { std::cout << "foo" << std::endl; } 
}; 

void bar(const A &a) { a.foo(); } 
void baz() { std::cout << "baz" << std::endl; } 

} 

int main(int argc, char **argv) { 
    B::A a; 
    bar(a); 
    B::baz(); // simply calling baz() does not work 

    return 0; 
} 

它是如何bar(a)可以無需額外的資格叫什麼名字?我本來預計只有B::bar(a)會編譯。

當函數在名稱空間內沒有參數時,不會發生這種情況。

+5

查找「ADL」(參數依賴查詢)又名「Koenig查找」。 – nwp

+1

關於cppreference的ADL參考:http://en.cppreference.com/w/cpp/language/adl – NathanOliver

+0

謝謝,那很快:) – vukung

回答

6

根據ISO C++ 14標準,在§3.4.2:通常的不合格查找期間

當一個函數調用的後綴表達式是一個不合格-ID,其他命名空間不考慮可能會被搜索,並且在這些名稱空間中,名稱空間範圍的朋友函數或函數模板聲明不可見,可能會被發現。對搜索的這些修改取決於參數(以及模板參數,模板參數的名稱空間)的類型。

和以下:

對於在函數調用每個參數類型T,有一組零個或多個相關聯的命名空間和一組零個或多個相關聯的類來加以考慮。命名空間和類的組是由類型的函數的參數完全確定..

如果T是一個類類型(包括工會),其相關聯的類別是:類本身;它是其成員的類別(如果有的話);及其直接和間接的基類。 其關聯的名稱空間是其關聯類的最內層封閉名稱空間。

其實你甚至可以防止這種情況發生的封閉功能名稱:

(bar)(a); // doens't compile 

(B::bar)(a); // does compile 

心中也認爲這僅適用於最裏面的命名空間,這意味着在以下情況需要限定命名空間:

namespace B { 
    namespace C { 
    struct A {}; 
    } 

    void bar(const C::A& a) { ... } 
}