2012-07-23 73 views
8

我有一個模板類NB::B<T>從命名空間中的非模板類NA::A派生。 act<T>是一個模板函數,在其模板參數的實例上調用add_ref函數。具體而言,act<NB::B<int>>想要使用ADL在NB::B的基地名稱空間中找到add_ref。完整的例子如下:通過模板類的基的參數依賴查找

template<class T> 
void act() { 
    T* p = 0; 
    add_ref(p); // the failing line 
} 

namespace NA 
{ 
    struct A { }; 

    // I want ADL to find this: 
    void add_ref(A* p) { 
    } 
} 

namespace NB 
{ 
    // template class with non-template base 
    template <class T> 
    struct B: NA::A { }; 

    typedef B<int> Bi; 

    // using NA::add_ref; // fixes the problem 
} 

int main() 
{ 
    act<NB::Bi>(); 
} 

這個編譯好吧gcc(4.7.0)。並在Comeau在線。然而clang(3.1)失敗:

a.cpp:4:3: error: use of undeclared identifier 'add_ref' 

與此同時,標準如下:

3.4.2/2 ...

- 如果T是模板id,其相關的名稱空間和類是定義模板的名稱空間;對於成員模板,成員模板的類;與爲模板類型參數提供的模板參數類型(不包括模板模板參數)相關聯的名稱空間和類;在其中定義了任何模板模板參數的名稱空間;以及定義用作模板模板參數的任何成員模板的類。

令人驚訝的是,模板的基地沒有列爲關聯名稱空間的路徑。因此clang的行爲似乎是正確的。並且Comeaugcc正在接受不正確的程序。

與此同時,3.4.2/3指出using的論辯的命名空間沒有任何效果:

在考慮相關的命名空間,查找是一樣的,當相關的名稱空間被用作執行查找一個限定符(3.4.3.2)除了:

- 關聯名稱空間中的任何使用指令都將被忽略。

但是當我取消註釋using NA::add_refclang很樂意編譯測試。

把我的例子轉化爲現實的角度來看,可以認爲act是的boost::intrusive_ptr的方法,add_ref(A*)intrusive_ptr_add_ref(CBase*)B是一些模板,從基地CBase獲得。

這對於我有幾個問題:

  1. 我是不是正確的,clang的是正確的拒絕我的測試程序,並gccComeau不遵循標準?

  2. 是否有一個原因爲什麼標準指定這種不切實際的行爲(不允許將模板類庫作爲關聯的名稱空間)?

  3. clang錯誤接受我的測試程序與using NA::add_ref指令的理由3.4.2/3

  4. 我應該報告一個錯誤嗎? :)

P.S.我已閱讀clang Language Compatibility FAQ,但沒有找到答案。

+0

C++ 11模式有幫助嗎? C++ 11似乎已經澄清了措辭,因爲事實上'NB :: B '是一個類(它恰好是模板專業化),而不是模板。 (IIUC的規則是,與類型爲專業化的模板相關聯的名稱空間被*添加到與該類相關聯的命名空間中。) – 2012-07-23 19:39:50

+0

這不會很脆弱嗎?在某些時候,你可能會添加一個默認的'add_ref'實現,它總是比直接基地的相關命名空間更好的匹配? – pmr 2012-07-23 19:40:08

+0

@LucDanton,你是對的。這兩點(關於'class'和'template-id'的關聯名字空間)都適用於類「template-id」。 – 2012-07-24 10:26:41

回答

6

從n3337,這基本上是C++ 11與小的編輯的變化,3.4.2/2讀取:

對於在函數調用每個參數類型T [...]的集合 命名空間和類都通過以下方式確定:[...]

  • 如果T是一個類類型(包括工會),其相關聯的類別是:類本身;它是其成員的類別(如果有的話);和其直接和間接基類。其關聯的名稱空間是其關聯的類是其成員的名稱空間。 此外,如果T是一個類模板專業化,...

然後將其與基本上你的問題張貼在同一報價繼續。這裏的重要區別是此外,這意味着您引用(和我省略)的列表除了已經提到的名稱空間外,還包括基類所屬的名稱空間。

  1. Gcc和comeau是正確的,並且鏗鏘聲++在拒絕代碼時是錯誤的。

  2. <不適>

  3. 鏘++是錯誤的拒絕它沒有using NA::add_ref

  4. 是的,你應該報告一個錯誤。 看來它已經被報告和修復。

+1

他錯誤已經在前一段時間被報告並修復。 zhr bug是thang clang沒有對模板進行缺省處理以找到其基類(及其朋友聲明) – 2012-07-23 19:52:22

+0

謝謝@david-rodriguez-dribeas。這'進一步'澄清了這個問題。 – 2012-07-24 10:37:10

+0

@ johannes-schaub-litb,你有沒有機會記住你正在談論的錯誤的鏈接?我剛剛檢查了一個新建立的'clang'後備箱,該錯誤仍然存​​在。 – 2012-07-24 10:58:04