2010-07-15 89 views
4

我對模板專業化略有困惑。C++基本模板問題

我有類Vector2,Vector3其中有operator+=(其定義如下)。

Vector2& operator+=(const Vector2& v) { 

     x() += v.x(), y() += v.y(); 

     return *this; 
    } 

現在我想添加的通用加入特定的行爲和這樣說:

template <typename V> const V operator+(const V& v1, const V& v2) { 
    return V(v1) += v2; 
} 

編譯沒有問題,並同時適用於Vector2Vector3但是,讓我們說,我想有一個稍微更有效的「+」操作我Vector2,我希望它採取行動的下列方式(使用模板特)

template<> const Vector2 operator+(const Vector2& v1, const Vector2& v2) { 
    return Vector2(v1.x() + v2.x(), v1.y() + v2.y()); 
} 

這看起來好像沒什麼問題,但不幸的是將代碼這兩大塊之後對方使代碼失敗編譯

(鏈接錯誤說LNK2005: "Vector2 const operator+<Vector2>(Vector2 const &,Vector2 const &)" ([email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@Z) already defined in ...

什麼是我的錯誤,其中d我出錯了?

謝謝。

回答

7

如果專業化處於頭文件中,那麼您需要聲明inline以允許它包含在多個編譯單元中。

請注意,您實際上並不需要模板專門化;一個簡單的重載會做同樣的事情。

+2

過載將永遠是一個更好的選擇。 – 2010-07-15 12:13:32

3

把這個

template<> const Vector2 operator+(const Vector2& v1, const Vector2& v2); 
文件

template<> const Vector2 operator+(const Vector2& v1, const Vector2& v2) { 
    return Vector2(v1.x() + v2.x(), v1.y() + v2.y()); 
} 

的.cpp文件

+0

這可能比在頭文件中內聯定義效率要低。 – 2010-07-15 12:20:16

3

我不太確定你想遵循那條路。您定義爲模板的operator+將匹配任何類型和所有類型,可能會產生衝突。爲什麼你不爲每個向量提供一個簡單的非模板化的operator+

也有其他風格的問題:

Vector2& operator+=(const Vector2& v) { 
    x() += v.x(); // you don't need operator, here and it might 
       // be confusing if you don't have operator, priorities clear 
    y() += v.y(); 
    return *this; 
} 

另外:

// This should not be a template!!! 
template <typename V> const V operator+(V v1, const V& v2) { 
    return v1 += v2; 
} 

在某些情況下,如果operator+如上述所定義(如果第一個參數是一個臨時的編譯器可以的Elid副本),但它不能用你的定義刪除副本。

如您已經定義與operator+的問題是,編譯器將嘗試與使用任何類型:

struct non_sumable {}; 
int main() { 
    non_sumable a,b; 
    a + b;   // matches the template, tries to instantiate 
        // compiler error says that non_sumable does not 
        // have operator+=, which might be confusing 
}