4

我对模板专业化有点困惑。

我有 classes Vector2Vector3其中有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 &)" (??$?HVVector2@core@lf@@@core@lf@@YA?BVVector2@01@ABV201@0@Z) already defined in ...

我的错误是什么,我哪里出错了?

谢谢你。

4

3 回答 3

7

如果特化在头文件中,那么您需要声明它inline以允许它包含在多个编译单元中。

请注意,您实际上并不需要模板专业化;一个简单的重载也会做同样的事情。

于 2010-07-15T12:09:47.760 回答
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文件中。

于 2010-07-15T12:11:01.693 回答
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+按上述定义(如果第一个参数是临时参数),编译器可以省略副本,而不能使用您的定义省略副本。

您定义的问题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
}
于 2010-07-15T12:29:42.683 回答