开发者

C++ basic template question

开发者 https://www.devze.com 2023-01-07 16:06 出处:网络
I\'m slightly confused with template specialization. I have classes Vector2, Vector3 which have operator+= in it (which are defined the following way).

I'm slightly confused with template specialization.

I have classes Vector2, Vector3 which have operator+= in it (which are defined the following way).

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

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

      return *this;
   }

Now I want to add the generic addition behaviour and say something like:

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

This compiles fine and works for both Vector2 and Vector开发者_StackOverflow中文版3. But let's say I want to have a slightly more efficient "+" operation for my Vector2 and I want it to act the following way (using the template specialization):

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

This looks fine to me, but unfortunately placing these two chunks of code right after each other makes the code fail the compilation

(linker says error LNK2005: "Vector2 const operator+<Vector2>(Vector2 const &,Vector2 const &)" (??$?HVVector2@core@lf@@@core@lf@@YA?BVVector2@01@ABV201@0@Z) already defined in ...)

What is my error and where did I go wrong?

Thank you.


If the specialisation is in a header file, then you need to declare it inline to allow it to be included in more than one compilation unit.

Note that you don't actually need a template specialisation here; a simple overload will do the same thing.


put this

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

in your header file and

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

in a .cpp file.


I am not really sure you want to follow that path. The operator+ that you have defined as a template will match any and all types, possibly creating conflicts. Why don't you provide a simple non-templated operator+ for each of your vectors?

There are also other style issues:

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;
}

Also:

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

In some circumstances the compiler can elide the copy if operator+ is defined as above (if the first argument is a temporary), while it cannot elide the copy with your definition.

The problem with the operator+ as you have defined is that the compiler will try to use it with any type:

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
}
0

精彩评论

暂无评论...
验证码 换一张
取 消