2010-07-15 107 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 
}