Автоматически применять два сторонних класса?

Я использую две сторонние библиотеки, каждая из которых реализует собственный 2D-векторный класс. К сожалению, мне приходится работать с ними обоими, так что могу ли я в любом случае написать некоторые «дружественные» функции, чтобы одну можно было автоматически преобразовать в другую, когда я пытаюсь использовать их в функциях из другой библиотеки?


person mpen    schedule 17.08.2009    source источник


Ответы (3)


Операторы преобразования должны быть функциями-членами.

В подобных ситуациях я использовал шаблон функции convert<X,Y> с полной специализацией или перегрузками для каждой пары типов, которые я хочу "преобразовать". В этом случае вам не понадобится шаблон, только две перегрузки, по одной в каждом направлении, потому что для данного X есть только одна вещь, в которую вы его конвертируете.

Тогда редко возникает проблема переключения между одним и другим (заметным исключением является случай, когда вы используете код шаблона, который требует, чтобы один тип параметра был преобразован в другой). Вы можете легко увидеть в коде границу между двумя API, не внося особого шума.

Причина, по которой я часто сталкивался с этой ситуацией, заключается в написании уровней абстракции ОС: базовая ОС имеет один набор объектов или непрозрачных дескрипторов для различных концепций ОС, а API, который вы реализуете, имеет другой. Гораздо приятнее просто «преобразовать» один набор концепций в другой, не имея ConvertHostMutexToGuestMutex, ConvertGuestMutexToHostMutex, ConvertHostSocketOptsToGuestSocketOpts и т. д. Недостатком является обычный недостаток с широко распространенной перегрузкой, то есть не обязательно очевидно, где функции фактически определены.

person Steve Jessop    schedule 17.08.2009
comment
Ваше первое предложение было более или менее ответом, который я искал, и ваше решение кажется лучше, чем создание другого класса, который можно было бы использовать только на мгновение. Спасибо :) - person mpen; 17.08.2009

Автоматическая-трансляция кажется невозможной. Вы можете определить глобальную функцию преобразования и вызвать ее явно. Не могли бы вы опубликовать определение этих классов? Может получится какой-то трюк с наследованием.

Что-то вроде этого, но это не автоматическое литье:

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;
}
person Kirill V. Lyadvinsky    schedule 17.08.2009
comment
Вам действительно нужны определения? Они хранят значения x и y, вот и все. doc.trolltech.com/4.5/qvector.html и linuxuser.at/elements/doc/box2d/structb2_vec2.htm. Нетрудно преобразовать одно в другое, QVector(b2vec.x, b2vec.y) в основном... просто хотелось немного синтаксической красоты. - person mpen; 17.08.2009

Одним из способов было бы наследование от этих классов и предоставление операторов преобразования друг для друга. Но тогда вам придется использовать объекты производного класса в своем коде. Вот пример кода:

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;
}
person Naveen    schedule 17.08.2009
comment
Да... Я хотел избежать этого. Мне пришлось бы повторно реализовать все, что у них уже есть. - person mpen; 17.08.2009
comment
Тогда единственное, что я мог придумать, - это глобальная функция, которая выполняет преобразования. - person Naveen; 17.08.2009