|
Boost Users : |
From: Nindi Singh (nindi73_at_[hidden])
Date: 2006-11-01 20:06:12
OK did it .
<Phactory.h>
#ifndef PHACTORY_HEADER_GUARD
#define PHACTORY_HEADER_GUARD
#include<string>
#include<map>
#include<cassert>
#include<boost/shared_ptr.hpp>
#include<boost/variant.hpp>
#include<boost/utility.hpp>
#include<boost/static_assert.hpp>
#include<boost/mpl/size.hpp>
#include<boost/mpl/list.hpp>
#include<boost/mpl/at.hpp>
template<unsigned long i>
struct unsigned_long {enum {value=i};};
template<class BaseClass>
struct PhRegistraBase {
typedef typename boost::make_variant_over<typename BaseClass::variant_type_list::type>::type variant;
typedef std::map<std::string,variant> ParameterMap;
virtual boost::shared_ptr<BaseClass> RetrieveObject(const std::string &theKey,const ParameterMap& theMap )const=0;
};
template<class BaseClass>
class Phactory {
public:
typedef typename boost::make_variant_over<typename BaseClass::variant_type_list::type>::type variant;
typedef std::map<std::string,variant> ParameterMap;
bool Register(const std::string &theKey, const PhRegistraBase<BaseClass>* theRegistra){
return theInnerMap.insert(InnerMap::value_type(theKey,theRegistra)).second;
}
boost::shared_ptr<BaseClass> RetrieveObject(const std::string &id, const ParameterMap & theMap)const {
InnerMapIterator theIterator (theInnerMap.find(id));
if(theIterator==theInnerMap.end())return boost::shared_ptr<BaseClass>(static_cast<BaseClass *>(0));
return theIterator->second->RetrieveObject(id,theMap);
}
private:
typedef typename std::map<std::string,const PhRegistraBase<BaseClass> *> InnerMap;
typedef typename std::map<std::string,const PhRegistraBase<BaseClass> *>::const_iterator InnerMapIterator;
std::map<std::string,const PhRegistraBase<BaseClass> *> theInnerMap;
};
#define CPARAM_1 boost::get<const boost::mpl::at_c<signature,0>::type &>(theMap.find(theVarNames[0])->second)
#define CPARAM_2 CPARAM_1, boost::get<const boost::mpl::at_c<signature,1>::type &>(theMap.find(theVarNames[1])->second)
#define CPARAM_3 CPARAM_2, boost::get<const boost::mpl::at_c<signature,2>::type &>(theMap.find(theVarNames[2])->second)
#define CPARAM_4 CPARAM_3, boost::get<const boost::mpl::at_c<signature,3>::type &>(theMap.find(theVarNames[3])->second)
#define CPARAM_5 CPARAM_4, boost::get<const boost::mpl::at_c<signature,4>::type &>(theMap.find(theVarNames[4])->second)
#define CPARAM_6 CPARAM_5, boost::get<const boost::mpl::at_c<signature,5>::type &>(theMap.find(theVarNames[5])->second)
#define CPARAM_7 CPARAM_6, boost::get<const boost::mpl::at_c<signature,6>::type &>(theMap.find(theVarNames[6])->second)
#define CPARAM_8 CPARAM_7, boost::get<const boost::mpl::at_c<signature,7>::type &>(theMap.find(theVarNames[7])->second)
#define CPARAM_9 CPARAM_8, boost::get<const boost::mpl::at_c<signature,8>::type &>(theMap.find(theVarNames[8])->second)
#define CPARAM_10 CPARAM_9, boost::get<const boost::mpl::at_c<signature,9>::type &>(theMap.find(theVarNames[9])->second)
#define INNER_RETRIVE_OBJECT(Nb) \
template<> boost::shared_ptr<BaseClass> InnerRetrieveObject< Nb >(const std::string &theKey,const ParameterMap& theMap)const{ \
CheckMap(theMap); \
return boost::shared_ptr<BaseClass>(new DerivedClass( CPARAM_##Nb ) \
); \
}
template
<
class BaseClass,
class DerivedClass
>
class PhRegistra:public PhRegistraBase<BaseClass>{
public:
typedef typename DerivedClass::constructor_signature_typelist signature;
typedef typename boost::make_variant_over<typename BaseClass::variant_type_list::type>::type variant;
typedef std::map<std::string,variant> ParameterMap;
enum {ssize = boost::mpl::size<signature>::value};
template<unsigned long i>
PhRegistra(const std::string &theKey, const char *theVariableNames[],const unsigned_long<i> *p=0)
{
BOOST_STATIC_ASSERT(i==ssize); // Must have ONE variable name for each paramter of the constructor
for(unsigned long i(0);i<ssize;++i) theVarNames[i]=std::string(theVariableNames[i]);
Singleton<Phactory<BaseClass> >::instance().Register(theKey,this);
}
boost::shared_ptr<BaseClass> RetrieveObject(const std::string &theKey,const ParameterMap& theMap)const{
return InnerRetrieveObject<ssize>(theKey,theMap);
}
template<int i>
boost::shared_ptr<BaseClass> InnerRetrieveObject(const std::string &theKey,const ParameterMap&)const;
INNER_RETRIVE_OBJECT(1)
INNER_RETRIVE_OBJECT(2)
INNER_RETRIVE_OBJECT(3)
INNER_RETRIVE_OBJECT(4)
INNER_RETRIVE_OBJECT(5)
INNER_RETRIVE_OBJECT(6)
INNER_RETRIVE_OBJECT(7)
INNER_RETRIVE_OBJECT(8)
INNER_RETRIVE_OBJECT(9)
INNER_RETRIVE_OBJECT(10)
private:
void CheckMap(const ParameterMap& theMap)const {
assert(theMap.size()==ssize);
for(unsigned long i(0);i<ssize;++i)assert(theMap.find(theVarNames[i])!=theMap.end());
}
std::string theVarNames[ssize];
};
#define PARAM_NAMES(n) n , static_cast<unsigned_long<sizeof(n)/sizeof(char*)> *>(0)
#endif
----------------- end of Phactory.h
<main,cpp>
#include<vector>
#include<iostream>
#include"Phactory.h"
using namespace std;
template<class Object>
//Quick liitle singletone just to demonstrate
class Singleton {
public:
static Object & instance(){static Object theObject;return theObject;}
virtual ~Singleton(){}
private:
Singleton();
Singleton(const Singleton<Object> & illegal);
Singleton<Object> & operator=(const Singleton<Object> & illegal){return *this;}
};
struct Dummy{};
struct Base {
typedef boost::mpl::list<double,int,unsigned long,std::string,std::vector<double>,float,Dummy> variant_type_list;
Base(){}
virtual void f()const=0;
virtual ~Base(){};
};
struct Derived :public Base {
typedef boost::mpl::list<double,int,std::string,std::vector<double> > constructor_signature_typelist;
Derived(double x_,int n_,const std::string &s_,const std::vector<double>&v_):
x(x_),n(n_),s(s_),v(v_){}
virtual void f()const{
cout << "My Double is " << x << "\n"
<< "My int is " << n << "\n"
<< "My String is " << s << "\n"
<< "My Vector Size is " << v.size() << "\n";
}
private:
double x;
int n;
std::string s;
std::vector<double> v;
};
namespace {
const char * theVarNames[]={"Double","Int","String","Vector"};
PhRegistra<Base,Derived> thePhRegistra(std::string("DerivedObject"),PARAM_NAMES(theVarNames));
}
int main() {
std::map<std::string,typename boost::make_variant_over<typename Base::variant_type_list::type>::type> theMap;
theMap["Double"]=1.0;
theMap["Int"]=1;
theMap["String"]="hello";
theMap["Vector"]=std::vector<double>(10);
boost::shared_ptr<Base>
thePtrSM(Singleton<Phactory<Base> >::instance().RetrieveObject("DerivedObject",theMap));
thePtrSM->f();
}
----- Original Message ----
From: Nindi Singh <nindi73_at_[hidden]>
To: boost-users_at_[hidden]
Sent: Wednesday, 1 November, 2006 8:59:31 PM
Subject: Re: [Boost-users] Boost ROCKS !!!!!
Cool !
Actualy I am now working another factory implementation.
In the new implementation, the Base Class will hold a typedef for a Boost Variant, and then the derived objects can be instantiated by the factory by being given a std::map of the variants and stripping out the values to make a call to the constructor of the derived class. The ONLY intrusion on the classes would be a typelist in the Base class to type the appropriate Boost::Variant and a typelist in the derived class identifing the signature of the constructor to be called by the factory, similar to the factory i have posted previously. The MPL really is VERY cool, and I think I have JUST touched the surface !!!. In fact I put my order in for 'C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond' at Amazon this afternoon !!!!
----- Original Message ----
From: Sohail Somani <s.somani_at_[hidden]>
To: boost-users_at_[hidden]
Sent: Wednesday, 1 November, 2006 8:46:28 PM
Subject: Re: [Boost-users] Boost ROCKS !!!!!
> -----Original Message-----
> From: boost-users-bounces_at_[hidden]
> [mailto:boost-users-bounces_at_[hidden]] On Behalf Of Nindi Singh
>
> 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.
[snip code]
Actually, I've been thinking of doing something similar and I am also
interested in what people say!
PS: Boost does rock
_______________________________________________
Boost-users mailing list
Boost-users_at_[hidden]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
All new Yahoo! Mail "The new Interface is stunning in its simplicity and ease of use." - PC Magazine
_______________________________________________
Boost-users mailing list
Boost-users_at_[hidden]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
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