0

I have two classes, a vertex and a vector, I am trying to use operators to make life simpler. If you'll examine the vector and vertex classes presented below I'm trying to implement operators in both vertex and vector.

For example VertexA+VertexB = VectorC //Isn't used that much...

VertexA-VertexB = VectorC //Could be used very frequently

VertexA+VectorB = VertexC //Could be used very frequently

VertexA-VectorB = VertexC //Could be used very frequently

VectorA+VectorB = VectorC //used

VectorA-VectorB = VectorC //used

VectorA+VertexB = VertexC //used

VectorA-VertexB = VertexC //used

If you'll notice there is a circular dependency. In order for the operators of one class to return by value( not by reference or pointer)

I know one work around, express vertexes just as vectors. However I was wondering if there was a different solution because I like the two different classes just for clarity.

#ifndef decimal
    #ifdef PRECISION
        #define decimal double
    #else
        #define decimal float
    #endif
#endif
class Vector;
class Vertex{
public:
    decimal x,y;
    const Vertex operator+(const Vector &other);
    const Vertex operator-(const Vector &other);
    const Vector operator+(const Vertex &other);
    const Vector operator-(const Vertex &other);
};

class Vector{
public:
    decimal x,y;
    const Vector operator+(const Vector &other) const {
        Vector result;
        result.x=this->x+other.x;
        result.y=this->y+other.y;
        return result;
    }
    const Vector operator-(const Vector &other) const {
        Vector result;
        result.x=this->x-other.x;
        result.y=this->y-other.y;
        return result;
    }
    const Vertex operator+(const Vertex &other) const {
        Vertex result;
        result.x=this->x+other.x;
        result.y=this->y+other.y;
        return result;
    }
    const Vertex operator-(const Vertex &other) const {
        Vertex result;
        result.x=this->x-other.x;
        result.y=this->y-other.y;
        return result;
    }
    decimal dot(const Vector &other) const{
        return this->x*other.x+this->y*other.y;
    }
    const decimal cross(const Vector &other) const{
        return this->x*other.y-this->y*other.x;
    }
};
user1659134
  • 93
  • 2
  • 7

2 Answers2

0

To make code of this type of things (Arithmetic data types) easy to write, normally I use a set of templates called "Operator overloading helpers", like Boost operators header. Checkout my implementation.

The advantage of this approach is that the implementation of the operators is coherent (operator+=implementation is coherent with operator+implementation, etc).

In your case, if you only implement Vertex& operator+=(const Vector& other) , Vertex& operator-=(const Vector& other) , Vector& operator+=(const Vector& other) , and Vector& operator-=(const Vector& other); you cover your 3th to 5th cases. How?

Check this code:

//Forward declaration needed:
class Vector;

struct Vertex : public dl32AdditionHelper<Vertex , Vector , true>,      //The last parameter is used to enable operator+ simmetry. That is, this covers cases 3 and 7.
                public dl32SubstractionHelper<Vertex , Vector , false>, //This covers case 4 (Simmetry si not enabled, see note bellow).
{
    float x , y;

    //For Vertex + Vector = Vertex
    Vertex& operator+=(const Vector& other)
    {
        x += other.x;
        y += other.y;

        return *this;
    }

    //For Vertex - Vector = Vertex
    Vertex& operator-=(const Vector& other)
    {
        x += other.x;
        y += other.y;

        return *this;
    }
};

struct Vector : public dl32AdditionHelper<Vector>,     //This covers case 5.
                public dl32SubstractionHelper<Vector>, //This covers case 6.
{
    float x , y;

    //For Vector + Vector = Vector
    Vector& operator+=(const Vector& other)
    {
        x += other.x;
        y += other.y;

        return *this;
    }

    //For Vector - Vector = Vector
    Vector& operator-=(const Vector& other)
    {
        x += other.x;
        y += other.y;

        return *this;
    }
};

Thats all.

Symmetry note: Symmetry property implies that operation a # b its equal to b # a, for a given operator #. Arithmetic helpers uses this feature to provide symmetric operators. For example, matrix algebra: m1 + m2 == m2 + m1, so operator+(const matrix_type_2& m1 , const matrix_type_1& m2) is implemented as m2 + m1 (A call to operator+(const matrix_type_1& m1 , const matrix_type_2& m2)). As you can see, symmetry not works for case 8.

My helpers implementation uses the type of the first parameter as return type of the operator. This is the reason why your other cases are not covered. But that cases implies a conversion from Vector to Vertex or/and viceversa. If you modify the implementation to do that, your all cases could be covered.

Manu343726
  • 13,969
  • 4
  • 40
  • 75
  • Sorry about this, but my forward declaration was working. Turns out I had a different issue which was causing a compiler error that made me think I couldn't do this at all. But it succeeded fine the way it is. – user1659134 Jul 03 '13 at 02:12
0

Forward declaration actually solved my problems. The compiling issue I got was because my function signatures didn't match correctly in a not obvious way.

user1659134
  • 93
  • 2
  • 7