2014-08-31 67 views
6

有了下面這段代碼我得到警告:警告:在不同的命名空間模板的專業化

warning: specialization of ‘template<class _Iterator> struct std::iterator_traits’ in different namespace [-fpermissive]

template<> class std::iterator_traits<Token_ptr>{ 
public: 
    typedef Word difference_type; 
    typedef Word value_type; 
    typedef Token_ptr pointer; 
    typedef Word& reference ; 
    typedef std::bidirectional_iterator_tag iterator_category ; 
}; 

雖然一切正常,沒有任何機構確切地知道什麼樣的手段,爲什麼發警告。 (g ++在clang ++不會發出警告)。

+0

這似乎是與[本問題]中報告的問題相同的問題(http://stackoverflow.com/questions/25311512/specialization-of-template-in-different-namespace)。 – nonsensickle 2017-04-27 10:36:04

+0

[爲什麼不允許模板專門化在不同的名稱空間](http://stackoverflow.com/questions/3072248/why-arent-template-specializations-allowed-to-be-in-different-namespaces)可能也是有趣的。 – nonsensickle 2017-04-27 10:44:08

回答

12

假設你在編寫本C++ 11模式(因爲鐺沒有給出警告信息),這是專門在全局命名空間,那麼就沒有錯,你的代碼。這是一個g ++的錯誤。 §14.7.3[temp.expl.spec]/p2:

顯式專用化應在專用模板中包含 的名稱空間中聲明。如果聲明者ID爲未被限定,則應在模板的最近的封閉名稱空間中聲明明確的特化,或者如果名稱空間內聯 (7.3.1),則從其封閉名稱空間集中聲明任何名稱空間。這樣的聲明也可能是一個定義。如果聲明不是 定義,專業化可以稍後定義(7.3.1.2)。

的全局命名空間是一個「命名空間封閉的專用模板」,和你聲明符-ID合格與std::,所以第二句不適用。作爲一種解決方法,你可以做什麼cdhowie的答案建議 - 即,打開namespace std區塊並將專業化放在那裏。

參見CWG issue 374GCC bug 56480

+1

多煩人。看來gcc沒有修復它,直到版本7.0 – Justin 2017-06-26 19:00:16

5

這裏有一個明顯的問題,以及一個潛在的隱形問題。可見的問題是該代碼不在namespace std塊中。要專門化模板,您需要位於您正在專門研究的模板的名稱空間內。在這種情況下,將名稱空間名稱作爲類型的一部分實際上不起作用。所以,你需要這樣做:

namespace std 
{ 
    template<> class iterator_traits<Token_ptr>{ 
    public: 
     typedef Word difference_type; 
     typedef Word value_type; 
     typedef Token_ptr pointer; 
     typedef Word& reference ; 
     typedef std::bidirectional_iterator_tag iterator_category ; 
    }; 
} 

另一個潛在的問題是,該代碼可能已經是另一namespace塊內(我不能說,因爲這大概不是全部源文件)。如果是,則需要先關閉該名稱空間塊,以使namespace std不嵌套在任何其他名稱空間塊中。

延伸閱讀:Specialization of 'template<class _Tp> struct std::less' in different namespace