2014-02-28 53 views
1

時,我遇到了非常相似的題目問題解決在這裏: How to properly specialize a templatized static const member that is the same type as its parent避免多重定義符號專業了模板化的靜態const成員

這裏是我的代碼:

template <class T> 
class p3d 
{ 
public: 
    p3d() { 
     x = 0; 
    } 

    p3d(const T &_x) { 
     x = _x; 
    } 

    static const p3d<T> origin; 

    T x; 
}; 

typedef p3d<float> p3df; 

int main(int, char**) 
{ 
    p3df p = p3df::origin; 
    return 0; 
} 

// elsewhere in a *.cpp file 
template<> const p3df p3df::origin(0.0f); 

當在嚴格編譯編譯器像鐺,我得到以下錯誤:

explicit specialization of 'origin' after instantiation 
template<> const p3df p3df::origin(0.0f); -> implicit instantiation first required here 

的解決方案是移動

template<> const p3df p3df::origin(0.0f); 

要在typedef之前。該解決方案的問題在於它會導致多重定義的符號,因爲現在每個使用矢量標頭的文件中都定義了p3df::origin。有什麼方法可以正確地專門化靜態常量typedef-ed模板,同時避免使用typedef在所有源文件中重複定義?

回答

1

只需推動main()功能前行

template<> const p3df p3df::origin(0.0f); 

,但typedef後。

我真的不知道問題在這裏。看起來clang似乎抱怨說你在之後提供了一個模板專門化的定義。 gcc/4.9(每晚構建)沒有問題。

一般來說,在頭文件中有一個靜態模板定義是很酷的,因爲它們 - 顧名思義 - 模板。但是,如果專門化模板,從而使其成爲實際類,則對任何常規類應用一個定義規則,並且您需要將定義移至非頭文件。

+0

我同意,當代碼全部位於單個文件中時,先移動該模板即可正常工作。但是因爲會有多個源文件,包括p3d類的頭文件,這也意味着會有多個「template <> const p3df p3df :: origin(0.0f);」的實例,並且在鏈接時,Clang(和大多數其他編譯器)將由於乘法定義的符號而失敗。 –