tags:

views:

103

answers:

3

I'm using two 3rd party libraries, which both implement their own 2D vector class. Unfortunately, I have to work with both of them, so is there anyway I can write some "friend" functions so that one can automatically be converted to the other when I try to use them in functions from the other library?

+1  A: 

Auto-cast seems not to be possible. You could define global conversion function and call it explicitly. Could you post definition of that classes? May be some trick with inheritance will be possible.

Something like this, but it is not auto-cast:

class T1 {};
class T2 {};

class UnionType : public T1, public T2
{
public:
    UnionType( const T1& val ) {} // real storing should be here
    UnionType( const T2& val ) {} // real storing should be here

    operator T1() { T1 t; return t; } // real conversion should be here
    operator T2() { T2 t; return t; } // real conversion should be here
};

int main()
{
    T1 t;
    T2 t2 = UnionType(t);

    return 0;
}
Kirill V. Lyadvinsky
Do you really need the definitions? They store x and y values, that's about it. http://doc.trolltech.com/4.5/qvector.html and http://linuxuser.at/elements/doc/box2d/structb2_vec2.htm. It's not hard to convert from one to the other, QVector(b2vec.x, b2vec.y) basically... just wanted some syntactic prettiness.
Mark
+1  A: 

One way would be to derive from those classes and provide conversion operators for one another. But then you have to use the derived class objects through out your code. Here is some sample code:

class ThirdParty1
{
    public:
     ThirdParty1(int x, int y) : m_x(x), m_y(y)
     {
     }
     int getX() const { return m_x; }
     int getY() const { return m_y; }

    private:
     int m_x;
     int m_y;
};

class ThirdParty2
{
    public:
     ThirdParty2(int x, int y) : m_x(x), m_y(y)
     {
     }
     int getX() const { return m_x; }
     int getY() const { return m_y; }

    private:
     int m_x;
     int m_y;
};

template<class Type, class AdaptedType>
class TP1Adaptor : public Type
{
    public:
     TP1Adaptor(int x, int y): Type(x,y)
     {
     } 
     operator AdaptedType()
     {
      return AdaptedType(getX(),getY());
     }


};

typedef TP1Adaptor<ThirdParty1, ThirdParty2> First2D;
typedef TP1Adaptor<ThirdParty2, ThirdParty1> Second2D;

void f(ThirdParty1 tp)
{
}


void f1(ThirdParty2 tp)
{
}


int  main()
{
    First2D f(0,0);
    f1(f);


    return 0;
}
Naveen
Yeah... I wanted to avoid that. I'd have to re-implement everything they've already got.
Mark
Then only thing I could think of is a global function which does the conversions.
Naveen
+1  A: 

Conversion operators have to be member functions.

In situations like this, I have used a convert<X,Y> function template, with full specialisations or overloads for each pair of types that I want to "cast". In this case, you wouldn't need the template, just two overloads, one in each direction, because for a given X there's only ever one thing you convert it to.

Then it's rarely any trouble to switch between one and the other (the notable exception being when you're using template code which requires that one parameter type be convertible to another). You can easily see in the code the boundary between the two APIs, without introducing much noise.

The reason I've had this situation a lot is writing OS abstraction layers - the underlying OS has one set of objects or opaque handles for various OS concepts, and the API you're implementing has another. It's much nicer to just "convert" from one set of concepts to the other, without having ConvertHostMutexToGuestMutex, ConvertGuestMutexToHostMutex, ConvertHostSocketOptsToGuestSocketOpts etc. The disadvantage is the usual one with widespread overloading, that it's not necessarily obvious where the functions are actually defined.

Steve Jessop
Your first sentence was more or less the answer I was looking for, and your solution seems better than creating another class which would only get used for an instant. Thanks :)
Mark