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@yahoo.co.uk>
To: boost-users@lists.boost.org
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@fincad.com>
To: boost-users@lists.boost.org
Sent: Wednesday, 1 November, 2006 8:46:28 PM
Subject: Re: [Boost-users] Boost ROCKS !!!!!

> -----Original Message-----
> From: boost-users-bounces@lists.boost.org
> [mailto:boost-users-bounces@lists.boost.org] 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@lists.boost.org
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@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users


Send instant messages to your online friends http://uk.messenger.yahoo.com