|
Boost Users : |
From: Nindi Singh (nindi73_at_[hidden])
Date: 2006-11-01 15:12:22
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.
<Factory.h>
#ifndef FACTORY_HEADER_GUARD
#define FACTORY_HEADER_GUARD
#include<string>
#include<map>
#include"Singleton.h"
#include<boost/shared_ptr.hpp>
#include<boost/mpl/size.hpp>
#include<boost/mpl/list.hpp>
#include<boost/mpl/at.hpp>
//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<typename BaseClass::Constructor_TypeList,0>::type P1
#define PARAM_2 PARAM_1 , typename boost::mpl::at_c<typename BaseClass::Constructor_TypeList,1>::type P2
#define PARAM_3 PARAM_2 , typename boost::mpl::at_c<typename BaseClass::Constructor_TypeList,2>::type P3
#define PARAM_4 PARAM_3 , typename boost::mpl::at_c<typename BaseClass::Constructor_TypeList,3>::type P4
#define PARAM_5 PARAM_4 , typename boost::mpl::at_c<typename BaseClass::Constructor_TypeList,4>::type P5
#define PARAM_6 PARAM_5 , typename boost::mpl::at_c<typename BaseClass::Constructor_TypeList,5>::type P6
#define PARAM_7 PARAM_6 , typename boost::mpl::at_c<typename BaseClass::Constructor_TypeList,6>::type P7
#define PARAM_8 PARAM_7 , typename boost::mpl::at_c<typename BaseClass::Constructor_TypeList,7>::type P8
#define PARAM_9 PARAM_8 , typename boost::mpl::at_c<typename BaseClass::Constructor_TypeList,8>::type P9
#define PARAM_10 PARAM_9 , typename boost::mpl::at_c<typename BaseClass::Constructor_TypeList,9>::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<BaseClass,Key,n>{};
// 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<BaseClass,Key,0> {
public:
bool Register(const Key & theKey,RegistraBase<BaseClass,Key,0> *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<BaseClass *>(0));
return theIterator->second->RetrieveObject(Q0);
}
private:
typedef typename std::map<Key,RegistraBase<BaseClass,Key,0> *> InnerMap;
typedef typename std::map<Key,RegistraBase<BaseClass,Key,0> *>::const_iterator InnerMapIterator;
std::map<Key,RegistraBase<BaseClass,Key,0> *> 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 \
> \
class Factory<BaseClass,Key,NnN> { \
public: \
bool Register(const Key & theKey,RegistraBase<BaseClass,Key,NnN> *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<BaseClass *>(0)); \
return theIterator->second->RetrieveObject(Q##NnN ); \
} \
private: \
typedef typename std::map<Key,RegistraBase<BaseClass,Key,NnN> *> InnerMap; \
typedef typename std::map<Key,RegistraBase<BaseClass,Key,NnN> *>::const_iterator InnerMapIterator; \
std::map<Key,RegistraBase<BaseClass,Key,NnN> *> 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<class BaseClass,typename Key> struct RegistraBase<BaseClass,Key,NnN> { \
virtual boost::shared_ptr<BaseClass> RetrieveObject(PARAM_##NnN)const=0; \
}; \
template<class BaseClass,class Derived,typename Key> \
struct Registra<BaseClass,Derived,Key,NnN>:public RegistraBase<BaseClass,Key,NnN> { \
Registra(const Key & theKey){Singleton<Factory<BaseClass,Key,NnN> >::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
<main.cpp>
#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<MyClassVoid,MyClassVoidDerived> 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<MyClassDouble,MyClassDouble> theRegistra(std::string("MyClassDouble"));
Registra<MyClassDouble,MyClassDoubleDerived> theRegistraD(std::string("MyClassDoubleDerived"));
}
struct MyClassMultiple {
typedef boost::mpl::list<std::string,std::vector<double>,double,MyClassDoubleDerived > Constructor_TypeList;
MyClassMultiple(std::string,std::vector<double>,double,MyClassDoubleDerived){}
virtual void f(){cout << " I am in MyClassMultiple \n";}
virtual ~MyClassMultiple(){};
};
namespace {
Registra<MyClassMultiple,MyClassMultiple> theRegistraM(std::string("MyClassMultiple"));
}
int main() {
boost::shared_ptr<MyClassVoid> thePtrVoid(Singleton<Factory<MyClassVoid> >::instance().RetrieveObject("MyClassVoidDerived"));
thePtrVoid->f();
boost::shared_ptr<MyClassDouble> thePtrDoubleDerived(Singleton<Factory<MyClassDouble> >::instance().RetrieveObject("MyClassDoubleDerived",1.0));
thePtrDoubleDerived->f();
boost::shared_ptr<MyClassDouble> thePtrDouble(Singleton<Factory<MyClassDouble> >::instance().RetrieveObject("MyClassDouble",1.0));
thePtrDouble->f();
boost::shared_ptr<MyClassMultiple>
thePtrM(Singleton<Factory<MyClassMultiple> >::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
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net