2013-10-06 39 views
3

新書這個例子,我再現參數相關查找(ADL)例如,在396和Stroustrup的書(第4版)的397頁下面給出一些澄清:我需要相關的Stroustrup的約ADL

namespace N { 
    struct S { int i; }; 
    void f(S); 
    void g(S); 
    void h(int); 
}; 

struct Base { 
    void f(N::S); 
}; 

struct D : Base { 
    void mf(N::S); 

    void g(N::S x) 
    { 
     f(x); // call Base::f() 
     mf(x); // call D::mf() 
     h(1); // error: no h(int) available 
    } 
}; 

什麼上面的評論是正確的(我已經測試過),但是這似乎與筆者在下一段中所說的內容不一致:

在標準中,參數相關查找的規則是短語 根據相關命名空間(iso§3.4.2)。基本上:

  • 如果一個參數是一個類的成員,關聯的命名空間是類本身(包括其基類)和類的 包圍的命名空間。
  • 如果參數是名稱空間的成員,則關聯的名稱空間是封閉的名稱空間。
  • 如果參數是內置類型,則沒有關聯的名稱空間。

在該示例中,x,其具有類型N::S不是D類的成員,也不其基Base的。但它是namespace N的成員。根據上面的第二個項目符號,函數N::f(S)應該是所調用的函數,而不是Base::f()

以上也結果似乎不與在標準中段落3.4.2p2第二子彈,它說同意:

如果T是一個類類型(包括工會),其相關聯的類是: 該課程本身;它是其成員的類別(如果有的話);和它的 直接和間接基類。其關聯的名稱空間是其關聯的類是其成員的名稱空間的 。此外,如果T是類模板專業化,則其關聯的名稱空間和類別還包括:與爲模板類型參數 (不包括模板模板參數)提供的模板參數類型相關聯的名稱空間和類。任何 模板模板參數都是成員的名稱空間;以及用作模板模板參數的任何 成員的類都是成員。

+1

只有在通過常規查找找不到函數時,ADL纔會開始運行。 –

+0

@ n.m不正確。規則是如果正常查找找到本地實際函數聲明(即'{void f(); ..')或類成員函數,則ADL被禁用。所有其他正常發現的聲明(包括本地使用聲明)仍然允許ADL完成。 –

+1

@ n.m。如果這是真的,那麼當你在全局命名空間中爲你的類實現'operator <<'時,你將不能再編寫'std :: cout << std :: string(「Hello」);'。這當然不會發生。 –

回答

4

3.4.2/3X是由不合格查找(3.4.1)中產生的查找組並且讓Y是由參數依賴 查找產生的查找集(定義如下)。如果X包含

  • 類成員的聲明,或
  • 一個塊範圍函數聲明爲不是使用聲明,或
  • 宣告既不是一個函數或函數模板

然後Y是空的。否則...

所以基本上,當普通的查找找到成員函數或本地(塊範圍)函數聲明(或不是函數的東西)時,ADL不會啓動。當普通的查找找到一個獨立的命名空間範圍函數時,或者根本沒有發現任何東西時,它會啓動。

+0

我會接受你的回答。但是我仍然不理解3.4.2p3中的例子:'g(parm,1)',1是一個int,而不是一個float! – Belloc

+0

在'main'中有'extern void g(NS :: T,float);'的局部(塊範圍)聲明。這抑制了ADL,即每秒上面的項目符號點。 –