Question

ok, yesterday I posted almost identical question here , but I wasn't able to modify the answer(working) to my needs... I did not want to mess the other topic, so I have started new one.

So, I have 2 (actually about 15) structs, which can composed an object

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"; }
};

then I have:

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();
    }
};

and I want to use it like:

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();
}

(ints are just for example purposes)

So I have some template magic:

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
};

but I can not make it works :(

I know there is a lot of code, but this is actually minimal example... I have posted this code to ideone, to make it better for reading.

Thank you!

EDIT: (to ask questions in comments)

I am building system for AI and want to solve as much thing in compile time as I can. In this case, I am building system for movement behavior. My code supply many types of behavior like "Go to point", "Evade from", "Avoid obstacles" etc. This behaviors are in example above mentioned as A a, B. Each of this behavior has method like "performBehavior" and its return type can be combined with other "performBehavior".

So I want to put together specific behavior at compile time. eg. just A or A+C+D+F etc...

and then in my update do something like:

if behavior is consisted of "Go to point", than "performBehaviorGoTo"

if behavior is consisted of "Evade from", than "performBehaviorEvade"

...

this is very very short explanation, but hope I have made my point

Was it helpful?

Solution

You can do that with function overloading:

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(); }

And then:

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

    doStuff(m_cT);
}

It is not clear, whether you want to chain calls for A<B<...> >. If you do, then something like the following would do:

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)); 
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top