For the past few months I have been making more and more use of Boost, in fact I would say becoming more and more reliant on Boost, every so often introducing myslef to a new library. But discovering the MPL, well that was awsome. The first time I applied it was to implement a factory. I would NEVR have though of doing it this way WITHOUT the MPL. Any comments on my use ( or indeed abuse !) of Boost would be more than apprieciated.
#ifndef FACTORY_HEADER_GUARD
#define FACTORY_HEADER_GUARD
#include<string>
#include<map>
#include"Singleton.h"
#include
#include
#include
#include
//Constructors of different Hierachies take a different humber fo parameters , so we set up
//some helper macros, for constructirs taking up to 10 parameters. More can be defined if required
#define PARAM_0
#define PARAM_1 typename boost::mpl::at_c::type P1
#define PARAM_2 PARAM_1 , typename boost::mpl::at_c::type P2
#define PARAM_3 PARAM_2 , typename boost::mpl::at_c::type P3
#define PARAM_4 PARAM_3 , typename boost::mpl::at_c::type P4
#define PARAM_5 PARAM_4 , typename boost::mpl::at_c::type P5
#define PARAM_6 PARAM_5 , typename boost::mpl::at_c::type P6
#define PARAM_7 PARAM_6 , typename boost::mpl::at_c::type P7
#define PARAM_8 PARAM_7 , typename boost::mpl::at_c::type P8
#define PARAM_9 PARAM_8 , typename boost::mpl::at_c::type P9
#define PARAM_10 PARAM_9 , typename boost::mpl::at_c::type P10
#define Q0
#define Q1 P1
#define Q2 Q1, P2
#define Q3 Q2, P3
#define Q4 Q3, P4
#define Q5 Q4, P5
#define Q6 Q5, P6
#define Q7 Q6, P7
#define Q8 Q7, P8
#define Q9 Q8, P9
#define Q10 Q9, P10
// One Registration object per class in a hireachy, this is the template blue print for the base classes of
// the registration objects
template
<
class BaseClass,
typename Key = std::string,
unsigned long = boost::mpl::size<typename BaseClass::Constructor_TypeList>::value
struct RegistraBase {};
// This is the template blue print for the concrete classes of
// the registration objects
template
<
class BaseClass,
class Derived,
typename Key = std::string,
unsigned long n = boost::mpl::size<typename BaseClass::Constructor_TypeList>::value
struct Registra :public RegistraBase{};
// This is the factory template blue print of the Factory class
template
<
class BaseClass,
typename Key = std::string ,
unsigned long n = boost::mpl::size<typename BaseClass::Constructor_TypeList>::value
class Factory {};
// This is the Factory 'concrete' class for Hireachies where the constrcutors tales no parameters
template
<
class BaseClass,
typename Key
\
class Factory { \
class Factory {
public:
bool Register(const Key & theKey,RegistraBase *theRegistra){
return theInnerMap.insert(InnerMap::value_type(theKey,theRegistra)).second;
}
boost::shared_ptr<BaseClass> RetrieveObject(const Key &id )const {
InnerMapIterator theIterator (theInnerMap.find(id));
if(theIterator==theInnerMap.end())return boost::shared_ptr<BaseClass>(static_cast(0));
return theIterator->second->RetrieveObject(Q0);
}
private:
typedef typename std::map *> InnerMap;
typedef typename std::map *>::const_iterator InnerMapIterator;
std::map *> theInnerMap;
};
// This is ta Macro definition Factory 'concrete' class for Hireachies where the constrcutors take
// a non xero number of parameters
#define FACTORY(NnN) \
template \
< \
class BaseClass, \
typename Key \
public: \
bool Register(const Key & theKey,RegistraBase *theRegistra){ \
return theInnerMap.insert(InnerMap::value_type(theKey,theRegistra)).second; \
} \
\
boost::shared_ptr<BaseClass> RetrieveObject(const Key &id,PARAM_##NnN )const { \
InnerMapIterator theIterator (theInnerMap.find(id)); \
if(theIterator==theInnerMap.end())return boost::shared_ptr<BaseClass>(static_cast(0)); \
return theIterator->second->RetrieveObject(Q##NnN ); \
} \
private: \
typedef typename std::map *> InnerMap; \
typedef typename std::map *>::const_iterator InnerMapIterator; \
std::map *> theInnerMap; \
};
FACTORY(1)
FACTORY(2)
FACTORY(3)
FACTORY(4)
FACTORY(5)
FACTORY(6)
FACTORY(7)
FACTORY(8)
FACTORY(9)
FACTORY(10)
// The macro defintions of the Registration Objects
#define REGISTRA(NnN) \
template struct RegistraBase { \
virtual boost::shared_ptr<BaseClass> RetrieveObject(PARAM_##NnN)const=0; \
}; \
template \
struct Registra:public RegistraBase { \
Registra(const Key & theKey){Singleton >::instance().Register(theKey,this);} \
boost::shared_ptr<BaseClass> RetrieveObject(PARAM_##NnN)const{return boost::shared_ptr<BaseClass>(new Derived(Q##NnN));} \
virtual ~Registra(){} \
};
REGISTRA(0)
REGISTRA(1)
REGISTRA(2)
REGISTRA(3)
REGISTRA(4)
REGISTRA(5)
REGISTRA(6)
REGISTRA(7)
REGISTRA(8)
REGISTRA(9)
REGISTRA(10)
#endif
----------------------------- end of Factory.h
#include<vector>
#include<iostream>
#include"Factory.h"
using namespace std;
struct MyClassVoid {
typedef boost::mpl::list<> Constructor_TypeList;
MyClassVoid(){}
virtual void f()const=0;
virtual ~MyClassVoid(){};
};
struct MyClassVoidDerived :public MyClassVoid {
MyClassVoidDerived(){}
virtual void f()const{cout << " I am in MyClassVoidDerived \n";}
virtual ~MyClassVoidDerived(){};
};
namespace {
Registra theRegistraVoid(std::string("MyClassVoidDerived"));
}
struct MyClassDouble {
typedef boost::mpl::list<double> Constructor_TypeList;
MyClassDouble(double){}
virtual void f(){cout << " I am in MyClassDouble \n";}
virtual ~MyClassDouble(){};
};
struct MyClassDoubleDerived :public MyClassDouble {
MyClassDoubleDerived(double x):MyClassDouble(x){}
virtual void f(){cout << " I am in MyClassDoubleDerived \n";}
virtual ~MyClassDoubleDerived(){};
};
namespace {
Registra theRegistra(std::string("MyClassDouble"));
Registra theRegistraD(std::string("MyClassDoubleDerived"));
}
struct MyClassMultiple {
typedef boost::mpl::list Constructor_TypeList;
MyClassMultiple(std::string,std::vector<double>,double,MyClassDoubleDerived){}
virtual void f(){cout << " I am in MyClassMultiple \n";}
virtual ~MyClassMultiple(){};
};
namespace {
Registra theRegistraM(std::string("MyClassMultiple"));
}
int main() {
boost::shared_ptr<MyClassVoid> thePtrVoid(Singleton::instance().RetrieveObject("MyClassVoidDerived"));
thePtrVoid->f();
boost::shared_ptr<MyClassDouble> thePtrDoubleDerived(Singleton::instance().RetrieveObject("MyClassDoubleDerived",1.0));
thePtrDoubleDerived->f();
boost::shared_ptr<MyClassDouble> thePtrDouble(Singleton::instance().RetrieveObject("MyClassDouble",1.0));
thePtrDouble->f();
boost::shared_ptr<MyClassMultiple>
thePtrM(Singleton::instance().RetrieveObject("MyClassMultiple",std::string("String"),std::vector<double>(2),1.0,MyClassDoubleDerived(1.0)));
thePtrM->f();
}
Send instant messages to your online friends http://uk.messenger.yahoo.com