Search code examples
c++templatesoperator-overloadingsfmlclass-template

Class inheritance and operator overloading


I'm learning C++ with a small project on SFML, and I wanted to extend the sf::Vector2<T> class, which represents a 2D math vector. The declaration of this class is available here. In particular, I wanted to add some methods to the class, for norm computation, rotation, etc.

This is what I have so far :

#include <cmath>
#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Transform.hpp>
#include <ostream>

namespace dw::math {

template <typename T>
class Vector2 : public sf::Vector2<T> {
public:
    // Don't really know what does that exactly means, explainations are welcome !
    using sf::Vector2<T>::Vector2;

    template <typename U>
    explicit Vector2(const U &vector) : sf::Vector2<T>(vector) {}

    // This ctor is for implicit conversion from base, don't know if it's really useful ?
    Vector2(sf::Vector2<T> &vector) : sf::Vector2<T>(vector) {}

    // Some methods here ...

    friend std::ostream & operator<<(std::ostream &os, const math::Vector2<T>& right) {
        os << '{' << right.x << ", " <<right.y << '}';
        return os;
    }
};

Later in the code, I have declared such a structure :

struct Derivative {
    dw::math::Vector2f dPos;
    dw::math::Vector2f dVel;

    Derivative() = default;
    Derivative(const dw::math::Vector2f &dPos, const dw::math::Vector2f &dVel) : dPos(dPos), dVel(dVel) {}

    Derivative operator+(const Derivative &rhs) const {
        return Derivative(
            dPos + rhs.dPos,
            dVel + rhs.dVel
        );
    }
}

The return part of the operator+ overloading of Derivative does not compile :

/home/palra/Documents/Projets/dw/src/physics/World.cpp: In member function ‘Derivative Derivative::operator+(const Derivative&) const’:
/home/palra/Documents/Projets/dw/src/physics/World.cpp:24:18: error: invalid user-defined conversion from ‘sf::Vector2<float>’ to ‘const Vector2f& {aka const dw::math::Vector2<float>&}’ [-fpermissive]
             dPos + rhs.dPos,
             ~~~~~^~~~~~~~~~
In file included from /home/palra/Documents/Projets/dw/src/physics/Body.h:8:0,
                 from /home/palra/Documents/Projets/dw/src/physics/World.h:10,
                 from /home/palra/Documents/Projets/dw/src/physics/World.cpp:5:
/home/palra/Documents/Projets/dw/src/physics/../math/Vector2.h:30:5: note: candidate is: dw::math::Vector2<T, <template-parameter-1-2> >::Vector2(sf::Vector2<T>&) [with T = float; <template-parameter-1-2> = void] <near match>
     Vector2(sf::Vector2<T> &vector) : sf::Vector2<T>(vector) {}

I don't understand why this doesn't work. the expression dPos + rhs.dPos is compatible with the call of sf::Vector2<float> operator +(const sf::Vector2<float>& left, const sf::Vector2<float>& right) because a dw::math::Vector2<float> is a sf::Vector2<float> by inheritance. This expression is then supposed to yield a sf::Vector2<float>, which is assignable to the dw::math::Vector2f thanks to the non explicit constructor I guess. Where I am wrong ? How am I supposed to get it work ?


Solution

  • sf::Vector<T> wasn't designed to be utilized as derived class, as such a better approach is to write free functions that extend the functionality of sf::Vector<T>, this works seamless for operators. Unfortunately for normal function calls C++ doesn't support extensions (yet) like C# does.