Boost logo

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