Как узнать, из каких типов состоит объект? - PullRequest
0 голосов
/ 10 августа 2011

хорошо, вчера я разместил почти идентичный вопрос здесь , но я не смог изменить ответ (рабочий) в соответствии с моими потребностями ... Я не хотел связываться с другой темой, поэтому яначали новый.

Итак, у меня есть 2 (на самом деле около 15) структур, которые могут составлять объект

class MyBase{};

template <typename Super, typename T1, typename T2> 
struct A : public Super 
{
    void doStuffA() { cout<<"doing something in A"; }
};

template <typename Super, typename T1, typename T2> 
struct B : public Super 
{
    void doStuffB() { cout<<"doing something in B"; }
};

, тогда у меня есть:

template <typename ComposedType, typename T1, typename T2>
class Combined
{
    ComposedType m_cT;
public:
    Combined(const ComposedType & c) : m_cT(c) { }

    typedef A<null, T1, T2> anull;
    typedef B<null, T1, T2> bnull;

    void update()
    {
        typedef typename split<ComposedType>::Ct Ct;
        typedef typename split<ComposedType>::At At;

        //this I want 
        if( composed of A ) 
            m_cT.doStuffA();

        if( composed of B ) 
            m_cT.doStuffB();
    }
};

и я хочу использовать его как:

int main()
{
    typedef A<B<MyBase,int,int>,int,int> ComposedType1;
    typedef B<MyBase,int,int> ComposedType2;

    ComposedType1 ct1;
    ComposedType2 ct2;

    Combined<ComposedType1, int, int> cb1(ct1);
    cb1.update();

    Combined<ComposedType2, int, int> cb2(ct2);
    cb2.update();
}

(целые числа только для примера)

Итак, у меня есть немного магии шаблона:

struct null{};

template<typename> 
struct split
{
    typedef null Ct;
    typedef null At;
};

template<template<typename> class C, typename T> 
struct split<C<T> >
{
    typedef C<null> Ct; //class template 
    typedef T      At;  //argument type
};

template<template<typename> class C> 
struct split<C<MyBase> >
{
    typedef C<null> Ct; //class template 
    typedef MyBase   At;  //argument type
};

но я могуне заставить его работать: (

Я знаю, что кода много, но на самом деле это минимальный пример ... Я разместил этот код на ideone , чтобы сделать его лучше для чтения.

Спасибо!

РЕДАКТИРОВАТЬ: (задавать вопросы в комментариях)

Я строю систему для ИИ и хочу решить как можно больше вещейво время компиляции, насколько я могу. В этом случае я строю систему для поведения движения. Мой код обеспечивает много типов поведения, таких как «Перейти к точке», «Уклониться от», «Избегать препятствий»les "и т. д. Это поведение в приведенном выше примере упоминается как A a, B. У каждого из этих поведений есть метод, подобный" executeBehavior ", и его тип возвращаемого значения можно комбинировать с другим" executeBehavior ".

Так что я хочусобрать определенное поведение во время компиляции.например.просто A или A + C + D + F и т.д. ...

, а затем в моем обновлении сделайте что-то вроде:

, если поведение состоит из «Перейти к точке», чем «executeBehaviorGoTo»

если поведение состоит из "уклонения от", чем "executeBehaviorEvade"

...

это очень очень краткое объяснение, но надеюсь, что я высказал свою точку зрения

1 Ответ

2 голосов
/ 10 августа 2011

Вы можете сделать это с перегрузкой функции:

template <typename Super, typename T1, typename T2> 
void doStuff(A<Super, T1, T2>& a) { a.doStaffA(); }

template <typename Super, typename T1, typename T2> 
void doStuff(B<Super, T1, T2>& b) { b.doStaffB(); }

А затем:

// ...
void update()
{
    //this I want 
    //if( composed of A ) 
    //    m_cT.doStuffA();
    //if( composed of B ) 
    //    m_cT.doStuffB();

    doStuff(m_cT);
}

Не ясно, хотите ли вы объединить вызовы для A<B<...> >.Если вы это сделаете, то подойдет что-то вроде следующего:

template <class T> 
void doStuff(T&) { /* do nothing */ }

template <typename Super, typename T1, typename T2> 
void doStuff(A<Super, T1, T2>& a) { 
    a.doStaffA(); 
    doStuff(static_cast<Super&>(a)); 
}

template <typename Super, typename T1, typename T2> 
void doStuff(B<Super, T1, T2>& b) { 
    b.doStaffB(); 
    doStuff(static_cast<Super&>(b)); 
}
...