Strong Typed generic Composite class

M

ManicQin

Hello everyone and especially Kai-Uwe Bux
A month ago I post a question in the same name of this one but I didnt
managed to explain my question right, so people didn't understand me.
Now when I have the time to post it again I hope I could manage to
explain my self + to post the answer to my previous question.

So...
When you look at the Composite GOF pattern it's basically

//Snip
class Interface
{
virtual void work() = 0;
}

class compositor : public Interface
{
void work()
{ //Iterate through all the instances that the
//Class holds and call their work function
}
void addItem(Interface* newItem)
{ //you get the point }

vector<Interface*> m_Items
};
class workerA : public Interface {}
class workerB : public Interface {}
//Snip

If you want to add a new different class that inherits from a new
different Interface you will need to Copy Paste a new compositor.
If you want to Generalize the compositor you are heading to the
problem of how to keep it strong typed.
You can always use a master Object that all object are descendants of
him but you
will loose the strong type characteristic.
You can create a all purpose compositor but than you loose the
polymorphism of the classes
(If your interface "working" function is go() and your compositor
"working" function is Iterate() you cannot use a pointer to the
interface to handle a compositor (thus loosing the point))
OK so I patched up a Strong Typed Generic Compositor I added the code
at the end
(BTW works on VS2008 Express but not on VS6)

My new problem is how to further generalize the function call,
I have two solutions
1) To add a template for each possible function
A template for a function that returns void and 1 arg
A template for a function that -""- -""- and 2 args
and so one .. I've seen it many time but I dislike this solution
2) To add another level of abstraction and to patch up
classes for retVals and argVals (a bit of meta programming)

What do you think is better

//snip
#include <iostream>
#include <vector>

using namespace std;

#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))


class IWorker
{
public:
virtual void work() = 0;
};

class ILaborer
{
public:
virtual void labor() = 0;
};

template <class T,void (T::*funcPtr)()>
class ABCCompositor
{
public:
typedef vector<T*> tItemVec;

void addItem(T* newItem)
{
m_ItemCol.push_back(newItem);
}

void IterateThrough()
{
for (tItemVec::iterator iDx = m_ItemCol.begin();
iDx < m_ItemCol.end(); iDx++)
{
CALL_MEMBER_FN(*(*iDx),funcPtr)();
}
}

protected:
tItemVec m_ItemCol;
};

class WorkerCompositor : public IWorker,
public ABCCompositor<IWorker,&IWorker::work>
{
public:

void work()
{
IterateThrough();
}
};

class LaborerCompositor : public ILaborer,
public ABCCompositor<ILaborer,&ILaborer::labor>
{
public:

void labor()
{
IterateThrough();
}
};

class CPrinter : public IWorker
{
public:
void work()
{
cout << "Hello" << endl;
}
};
class CPrinter2 : public IWorker
{
public:
void work()
{
cout << " OLA!!!" << endl;
}
};

class CPrinter3 : public ILaborer
{
public:
void labor()
{
cout << "Shalom" << endl;
}
};
class CPrinter4 : public ILaborer
{
public:
void labor()
{
cout << "Salam" << endl;
}
};

int main()
{

WorkerCompositor printSession1;
WorkerCompositor printSession2;

printSession1.addItem(new CPrinter);
printSession1.addItem(new CPrinter2);
printSession1.addItem(new CPrinter);
printSession1.addItem(new CPrinter2);
printSession1.addItem(new CPrinter);
printSession2.addItem(&printSession1);
printSession2.addItem(new CPrinter2);

printSession2.work();


LaborerCompositor printSession3;
LaborerCompositor printSession4;

printSession3.addItem(new CPrinter3);
printSession3.addItem(new CPrinter4);
printSession3.addItem(new CPrinter3);
printSession3.addItem(new CPrinter4);
printSession3.addItem(new CPrinter3);
printSession4.addItem(&printSession3);
printSession4.addItem(new CPrinter3);

printSession4.labor();
return 0;
}

//snip

Thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top