Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Basic operator overloading syntax in c++

I’m having a hard time forming a question of what I’m trying to ask so let me give you an example:

Say we are working on a 3d system where we have defined a vector class, Vec3. We overload some arithmetic operators for obvious resons. Among these we overload the *operator so that it will return the dot product of two vectors. Now our code should look something like this:

class Vec3{
private:
    float x, y, z;
public:
    float operator*(const Vec3&) const; //dot product
.
.
.

Now say that we want to be able to scale our vector by using the *operator with something, say a float. This could be done by declaring the following:

    Vec3 operator*(const float) const;
    friend Vec3 operator*(const float, const Vec3&);

This yeilds two overloads and I’m wondering if there’s a way to do it with just one, i.e. say we declare this instead of the above two lines:

    friend Vec3 operator*(const Vec3&, const Vec3&);

and then add default values for the Vec3 ctor to handle the convertion from float.

This last example would work for:

    Vec3 someVec3 = 1.0 * otherVec3; //through friend Vec3 operator*(const float, const Vec3&)

however not for this:

    Vec3 someVec3 = otherVec3 * 1.0;

as the compiler wouldn’t know which of the two to use:

    friend Vec3 operator*(const float, const Vec3&); //the one we want to use
or
    float operator*(const Vec3&) const; //the one for the dot product

Any suggestions?

Thank you!

like image 813
mushroombob Avatar asked Feb 06 '12 17:02

mushroombob


2 Answers

In this case I would initially advise against operator overloading, because how are your users to know if * represents dot or cross product (both are reasonable meanings depending on expected client use). I would actually suggest just not supporting operator* and do it with dot, cross and scale members. Then you don't have to worry about multiple overloads and it's clear to your users what they're getting.

However if you do want to go ahead with the operators, there's nothing wrong with having two overloads. Creating a dummy Vec3 to do scaling is not only semantically incorrect it's going to add a small amount of unneeded overhead.

like image 155
Mark B Avatar answered Sep 25 '22 11:09

Mark B


Boost.Operators can do most of the boiler-plate work for you. E.g.:

class Vec3 
  : boost::multipliable2<Vec3, float>
{
public:
   // ... 

   Vec3 operator*=(float);
   // Vec3 operator*(Vec3, const float&) and
   // Vec3 operator*(const float&, Vec3) auto-generated
   // by multipliable. 
};
like image 38
Georg Fritzsche Avatar answered Sep 23 '22 11:09

Georg Fritzsche