2011-08-05 41 views
2

我有一個模板化的容器對象。我正在嘗試爲float版本創建專門的構造函數。問題是,當編譯器試圖編譯使用float版本的第二個對象時,我得到一個multiple definition of錯誤。g ++中的模板規範編譯錯誤

注意:整個班級在h文件中。該文件包含一個定義(#ifndef#define#endif)。 g ++版本3.4.6。這可以與其他編譯器一起編譯,例如英特爾的icc。

代碼類似於以下內容:

template <typename T> 
class Container { 
public: 
    Container(); 
    virtual ~Container() {} 
private: 
    std::vector<T> data; 
    // other members 
}; 

template <> Container<float>::Container() { 
    // do something special 
} 

template <typename T> Container<T>::Container() { 
    // do default initialization 
} 

任何想法?謝謝!

編輯正在編譯的對象也將進入單獨的共享對象,不確定是否與它有關。

+1

g ++ 4.0.1也很好。升級? –

+0

目前,我無法這樣做,或者相信我會。我被鎖定到該版本的這個應用程序。 – steveo225

+0

只是爲了測試,我將代碼複製到了一個有g ++ 4.1.1的盒子,並得到了相同的錯誤。 – steveo225

回答

4

專業化仍然必須遵循單一定義規則,就像任何其他非模板方法一樣。將其標記爲內聯或在源文件中定義方法體(而不是標題)。

-4

你可以使用typeid

template <typename T> Container<T>::Container() { 
    if(typeid(T)==typeid(float)) { 
     // do something special 
    } 
    else { 
     // do default initialization 
    } 
} 

缺點:你不能使用初始化列表中爲您的特殊情況。 編輯: 當我寫這個答案時,我仍然認爲錯誤是由編譯器造成的,而不是由OP的代碼(沒有看太多)。然而,這種類型的方法是絕對有效的C++(請參閱下面的鏈接),如果模板確實無法在您的特定編譯器中正常工作,則它是一個相當不錯的解決方法,並且如果您一旦切換到編譯器更好。

示範:example @ ideone

+0

這不就是不好的設計嗎?因爲該嘗試拋棄了模板提供的所有可能性。 – tgmath

+0

這可能會導致編譯錯誤 –

+0

@tgmath:我aggree,最常使用'typeid'的代碼代表糟糕的設計。但在這種情況下,給'typeid'的參數是一個類型而不是一個對象,它並沒有那麼糟糕。當然,如果可能的話,你應該使用模板。 – smerlin

1
template <> Container<float>::Container() { 
    // do something special 
} 

是專業化的定義。甲專業化必須在每個編譯單元中聲明它用於:

template <> Container<float>::Container(); 

只有一個CU的限定。所以你的.h必須有聲明,你必須找到一個足夠的(可能是新的).cpp的定義。 (正如Mark B指出的那樣,使內聯專業化也是一種允許將定義放在需要的所有編譯單元中的方法)。

1

這很棘手。問題是你的專業化不是 模板,而是一個實際的功能定義。並且由於它位於 標題中,所以在包含它兩次時會得到多個定義。 是這樣的:

template<> Container<float>::Container(); 
在頭

,並在一個單一的源文件的執行。