N
Nindi
5 Files
Singleton.h The Singleton
Factory.h The factory creating new objects. The
Base class of the hierachy stores a typelist
identifying the signature of the constructors to
be called in the hierachy by the Factory
StaticFactory Returning refernences to a static object .. typelist
as above.
Phactory An implementation of an Abstract Factory. Each derived class
in a hierachy stores a typelist in itself to identify
the signature
of the constructor it would like the factory to use.
The correct constructor
is called in each derived class by the factory
main.cpp a demonstration of the factories
(Heavy reliance on Boost)
---------------------------------------------------
<main.cpp>
#include<vector>
#include<iostream>
#include"Factory.h"
#include"Phactory.h"
using namespace std;
struct MyClassVoid
{
typedef boost::mpl::list<> Constructor_TypeList;
MyClassVoid()
{}
virtual void f()const=0;
virtual ~MyClassVoid()
{}
;
};
struct MyClassVoidDerived ublic 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;
typedef boost::mpl::list<double> variant_type_list;
MyClassDouble(double)
{}
virtual void f()
{
cout << " I am in MyClassDouble \n";
}
virtual ~MyClassDouble()
{}
;
};
struct MyClassDoubleDerived ublic MyClassDouble
{
typedef boost::mpl::list<double> constructor_signature_typelist;
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
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"));
StaticRegistra<MyClassMultiple,MyClassMultiple>
theStaticRegistraM(std::string("MyClassMultiple"),std::string("String"),
std::vector<double>(2),1.0,MyClassDoubleDerived(1.0));
}
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 ublic Base
{
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()
{
char ch;
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);
cin >>ch;
}
-----------------------------------------------------------------------------------------------
<singleton.h>
#ifndef SINGLETON_HEADER_GUARD
#define SINGLETON_HEADER_GUARD
#include <boost/utility.hpp>
template<class Object>
struct Singleton :boost::noncopyable
{
static Object & instance()
{
static Object theObject;
return theObject;
}
virtual ~Singleton()
{}
}
;
#endif
---------------------------------------------------------------------------
<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>
#include<boost/preprocessor/repetition.hpp>
#include<boost/preprocessor/arithmetic/sub.hpp>
#ifndef MAX_FACTORIES
#define MAX_FACTORIES 10
#endif
// 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>::valuestruct 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>::valuestruct Registra ublic 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>::valueclass Factory
{}
;
//Helper Macros
#define PARAM(z,Nb,data) typename boost::mpl::at_c<typename
BaseClass::Constructor_TypeList,Nb>::type P##Nb
#define REGISTRABASE(z,Nb,data)\
template<class BaseClass,typename Key> struct
RegistraBase<BaseClass,Key,Nb> { \
virtual boost::shared_ptr<BaseClass>
RetrieveObject(BOOST_PP_ENUM(Nb,PARAM,~))const=0;\
};
BOOST_PP_REPEAT(MAX_FACTORIES,REGISTRABASE,~)
#define FACTORY(z,Nb,data)\
template\
<\
class BaseClass,\
typename Key\
public: \
bool Register(const Key & theKey,RegistraBase<BaseClass,Key,Nb>
*theRegistra){ \
return
theInnerMap.insert(InnerMap::value_type(theKey,theRegistra)).second; \
}\
\
boost::shared_ptr<BaseClass> RetrieveObject(const Key &id
BOOST_PP_COMMA_IF(Nb) BOOST_PP_ENUM(Nb,PARAM,~))const {\
InnerMapIterator theIterator (theInnerMap.find(id));\
if(theIterator==theInnerMap.end())return
boost::shared_ptr<BaseClass>(static_cast<BaseClass *>(0)); \
return theIterator->second->RetrieveObject(
BOOST_PP_ENUM_PARAMS(Nb,P));\
}\
private:\
typedef typename std::map<Key,RegistraBase<BaseClass,Key,Nb> *>
InnerMap;\
typedef typename std::map<Key,RegistraBase<BaseClass,Key,Nb>
*>::const_iterator InnerMapIterator;\
std::map<Key,RegistraBase<BaseClass,Key,Nb> *> theInnerMap;\
};
BOOST_PP_REPEAT(MAX_FACTORIES,FACTORY,~)
// The macro defintions of the Registration Objects
#define REGISTRA(z,Nb,data) \
template<class BaseClass,class Derived,typename Key>\
struct Registra<BaseClass,Derived,Key,Nb>ublic
RetrieveObject(BOOST_PP_ENUM(Nb,PARAM,~))const\
{return boost::shared_ptr<BaseClass>(new Derived(
BOOST_PP_ENUM_PARAMS(Nb,P)));}\
virtual ~Registra(){}\
};
BOOST_PP_REPEAT(MAX_FACTORIES,REGISTRA,~)
#undef MAX_FACTORIES
#undef PARAM
#undef REGISTRA
#undef REGISTRABASE
#undef FACTORY
#include"StaticFactory.h"
#endif
-----------------------------------------------------------------------------------
<StaticFactory.h>
#ifndef STATIC_FACTORY_HEADER_GUARD
#define STATIC_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>
#include<boost/preprocessor/repetition.hpp>
#include<boost/preprocessor/arithmetic/sub.hpp>
#ifndef MAX_STATIC_FACTORIES
#define MAX_STATIC_FACTORIES 10
#endif
template
<
class BaseClass,
typename Key = std::stringstruct StaticRegistraBase
{
virtual boost::shared_ptr<BaseClass> RetrieveObject()const=0;
}
;
template
<
class BaseClass,
class Derived,
typename Key = std::string,
unsigned long n = boost::mpl::size<typename
BaseClass::Constructor_TypeList>::valuestruct StaticRegistra ublic StaticRegistraBase<BaseClass,Key>
{}
;
template
<
class BaseClass,
typename Key=std::stringclass StaticFactory
{
public:
bool Register(const Key & theKey,StaticRegistraBase<BaseClass,Key>
*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();
}
private:
typedef typename std::map<Key,StaticRegistraBase<BaseClass,Key> *>
InnerMap;
typedef typename std::map<Key,StaticRegistraBase<BaseClass,Key>
*>::const_iterator InnerMapIterator;
std::map<Key,StaticRegistraBase<BaseClass,Key> *> theInnerMap;
};
//Helper Macros
#define PARAM(z,Nb,data) typename boost::mpl::at_c<typename
BaseClass::Constructor_TypeList,Nb>::type P##Nb
#define STATICREGISTRA(z,Nb,data) template<class BaseClass,class
Derived,typename Key>\
struct StaticRegistra<BaseClass,Derived,Key, Nb >ublic
StaticRegistraBase<BaseClass,Key> \
{\
StaticRegistra(const Key & theKey BOOST_PP_COMMA_IF(Nb)
BOOST_PP_ENUM(Nb,PARAM,~)): \
theObjectPtr(new Derived(BOOST_PP_ENUM_PARAMS(Nb,P)))\
{\
boost::shared_ptr<BaseClass> RetrieveObject()const{return
theObjectPtr;}\
virtual ~StaticRegistra(){} \
private: \
boost::shared_ptr<BaseClass> theObjectPtr; \
};
BOOST_PP_REPEAT(MAX_STATIC_FACTORIES,STATICREGISTRA,~)
#undef MAX_STATIC_FACTORIES
#undef PARAM
#undef STATICREGISTRA
#endif
-------------------------------------------------------------------------------------------------
<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>
#include<boost/preprocessor/repetition.hpp>
#ifndef MAX_PHACTORIES
#define MAX_PHACTORIES 10
#endif
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 PARAM(z,Nb,data) boost::get<const boost::mpl::at_c<signature,
Nb >::type &>(theMap.find(theVarNames[Nb])->second)
#define INNER_RETRIVE_OBJECT(z,Nb,data)\
CheckMap(theMap);\
return boost::shared_ptr<BaseClass>(new DerivedClass(
BOOST_PP_ENUM(Nb,PARAM,~) ) \
);\
}
template
<
class BaseClass,
class DerivedClassclass PhRegistraublic 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=std::string(theVariableNames);
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;
BOOST_PP_REPEAT(MAX_PHACTORIES,INNER_RETRIVE_OBJECT,~)
private:
void CheckMap(const ParameterMap& theMap)const
{
assert(theMap.size()==ssize);
for(unsigned long i(0);i<ssize;++i)
assert(theMap.find(theVarNames)!=theMap.end());
}
std::string theVarNames[ssize];
};
#define PARAM_NAMES(n) n ,
static_cast<unsigned_long<sizeof(n)/sizeof(char*)> *>(0)
#undef MAX_PHACTORIES
#undef PARAM
#undef INNER_RETRIVE_OBJECT
#endif
Singleton.h The Singleton
Factory.h The factory creating new objects. The
Base class of the hierachy stores a typelist
identifying the signature of the constructors to
be called in the hierachy by the Factory
StaticFactory Returning refernences to a static object .. typelist
as above.
Phactory An implementation of an Abstract Factory. Each derived class
in a hierachy stores a typelist in itself to identify
the signature
of the constructor it would like the factory to use.
The correct constructor
is called in each derived class by the factory
main.cpp a demonstration of the factories
(Heavy reliance on Boost)
---------------------------------------------------
<main.cpp>
#include<vector>
#include<iostream>
#include"Factory.h"
#include"Phactory.h"
using namespace std;
struct MyClassVoid
{
typedef boost::mpl::list<> Constructor_TypeList;
MyClassVoid()
{}
virtual void f()const=0;
virtual ~MyClassVoid()
{}
;
};
struct MyClassVoidDerived ublic 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;
typedef boost::mpl::list<double> variant_type_list;
MyClassDouble(double)
{}
virtual void f()
{
cout << " I am in MyClassDouble \n";
}
virtual ~MyClassDouble()
{}
;
};
struct MyClassDoubleDerived ublic MyClassDouble
{
typedef boost::mpl::list<double> constructor_signature_typelist;
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 said: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"));
StaticRegistra<MyClassMultiple,MyClassMultiple>
theStaticRegistraM(std::string("MyClassMultiple"),std::string("String"),
std::vector<double>(2),1.0,MyClassDoubleDerived(1.0));
}
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 ublic Base
{
Derived(double x_,int n_,const std::string &s_,consttypedef boost::mpl::list said:constructor_signature_typelist;
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()
{
char ch;
thePtrVoid->f();boost::shared_ptr said:::instance().RetrieveObject("MyClassVoidDerived"));
thePtrDoubleDerived->f();boost::shared_ptr said:::instance().RetrieveObject("MyClassDoubleDerived",1.0));
thePtrDouble->f();boost::shared_ptr said:::instance().RetrieveObject("MyClassDouble",1.0));
thePtrM->f();boost::shared_ptr said:::instance().RetrieveObject("MyClassMultiple",std::string("String"),std::vector<double>(2),1.0,MyClassDoubleDerived(1.0)));
thePtrSM->f();boost::shared_ptr said:::instance().RetrieveObject("MyClassMultiple"));
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);
thePtrPhM->f();boost::shared_ptr said:::instance().RetrieveObject("DerivedObject",theMap));
cin >>ch;
}
-----------------------------------------------------------------------------------------------
<singleton.h>
#ifndef SINGLETON_HEADER_GUARD
#define SINGLETON_HEADER_GUARD
#include <boost/utility.hpp>
template<class Object>
struct Singleton :boost::noncopyable
{
static Object & instance()
{
static Object theObject;
return theObject;
}
virtual ~Singleton()
{}
}
;
#endif
---------------------------------------------------------------------------
<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>
#include<boost/preprocessor/repetition.hpp>
#include<boost/preprocessor/arithmetic/sub.hpp>
#ifndef MAX_FACTORIES
#define MAX_FACTORIES 10
#endif
// 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>::valuestruct 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>::valuestruct Registra ublic 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>::valueclass Factory
{}
;
//Helper Macros
#define PARAM(z,Nb,data) typename boost::mpl::at_c<typename
BaseClass::Constructor_TypeList,Nb>::type P##Nb
#define REGISTRABASE(z,Nb,data)\
template<class BaseClass,typename Key> struct
RegistraBase<BaseClass,Key,Nb> { \
virtual boost::shared_ptr<BaseClass>
RetrieveObject(BOOST_PP_ENUM(Nb,PARAM,~))const=0;\
};
BOOST_PP_REPEAT(MAX_FACTORIES,REGISTRABASE,~)
#define FACTORY(z,Nb,data)\
template\
<\
class BaseClass,\
typename Key\
class Factory<BaseClass,Key,Nb> {\
public: \
bool Register(const Key & theKey,RegistraBase<BaseClass,Key,Nb>
*theRegistra){ \
return
theInnerMap.insert(InnerMap::value_type(theKey,theRegistra)).second; \
}\
\
boost::shared_ptr<BaseClass> RetrieveObject(const Key &id
BOOST_PP_COMMA_IF(Nb) BOOST_PP_ENUM(Nb,PARAM,~))const {\
InnerMapIterator theIterator (theInnerMap.find(id));\
if(theIterator==theInnerMap.end())return
boost::shared_ptr<BaseClass>(static_cast<BaseClass *>(0)); \
return theIterator->second->RetrieveObject(
BOOST_PP_ENUM_PARAMS(Nb,P));\
}\
private:\
typedef typename std::map<Key,RegistraBase<BaseClass,Key,Nb> *>
InnerMap;\
typedef typename std::map<Key,RegistraBase<BaseClass,Key,Nb>
*>::const_iterator InnerMapIterator;\
std::map<Key,RegistraBase<BaseClass,Key,Nb> *> theInnerMap;\
};
BOOST_PP_REPEAT(MAX_FACTORIES,FACTORY,~)
// The macro defintions of the Registration Objects
#define REGISTRA(z,Nb,data) \
template<class BaseClass,class Derived,typename Key>\
struct Registra<BaseClass,Derived,Key,Nb>ublic
boost::shared_ptr<BaseClass>RegistraBase said:::instance().Register(theKey,this);}\
RetrieveObject(BOOST_PP_ENUM(Nb,PARAM,~))const\
{return boost::shared_ptr<BaseClass>(new Derived(
BOOST_PP_ENUM_PARAMS(Nb,P)));}\
virtual ~Registra(){}\
};
BOOST_PP_REPEAT(MAX_FACTORIES,REGISTRA,~)
#undef MAX_FACTORIES
#undef PARAM
#undef REGISTRA
#undef REGISTRABASE
#undef FACTORY
#include"StaticFactory.h"
#endif
-----------------------------------------------------------------------------------
<StaticFactory.h>
#ifndef STATIC_FACTORY_HEADER_GUARD
#define STATIC_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>
#include<boost/preprocessor/repetition.hpp>
#include<boost/preprocessor/arithmetic/sub.hpp>
#ifndef MAX_STATIC_FACTORIES
#define MAX_STATIC_FACTORIES 10
#endif
template
<
class BaseClass,
typename Key = std::stringstruct StaticRegistraBase
{
virtual boost::shared_ptr<BaseClass> RetrieveObject()const=0;
}
;
template
<
class BaseClass,
class Derived,
typename Key = std::string,
unsigned long n = boost::mpl::size<typename
BaseClass::Constructor_TypeList>::valuestruct StaticRegistra ublic StaticRegistraBase<BaseClass,Key>
{}
;
template
<
class BaseClass,
typename Key=std::stringclass StaticFactory
{
public:
bool Register(const Key & theKey,StaticRegistraBase<BaseClass,Key>
*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();
}
private:
typedef typename std::map<Key,StaticRegistraBase<BaseClass,Key> *>
InnerMap;
typedef typename std::map<Key,StaticRegistraBase<BaseClass,Key>
*>::const_iterator InnerMapIterator;
std::map<Key,StaticRegistraBase<BaseClass,Key> *> theInnerMap;
};
//Helper Macros
#define PARAM(z,Nb,data) typename boost::mpl::at_c<typename
BaseClass::Constructor_TypeList,Nb>::type P##Nb
#define STATICREGISTRA(z,Nb,data) template<class BaseClass,class
Derived,typename Key>\
struct StaticRegistra<BaseClass,Derived,Key, Nb >ublic
StaticRegistraBase<BaseClass,Key> \
{\
StaticRegistra(const Key & theKey BOOST_PP_COMMA_IF(Nb)
BOOST_PP_ENUM(Nb,PARAM,~)): \
theObjectPtr(new Derived(BOOST_PP_ENUM_PARAMS(Nb,P)))\
{\
} \Singleton said:::instance().Register(theKey,this); \
boost::shared_ptr<BaseClass> RetrieveObject()const{return
theObjectPtr;}\
virtual ~StaticRegistra(){} \
private: \
boost::shared_ptr<BaseClass> theObjectPtr; \
};
BOOST_PP_REPEAT(MAX_STATIC_FACTORIES,STATICREGISTRA,~)
#undef MAX_STATIC_FACTORIES
#undef PARAM
#undef STATICREGISTRA
#endif
-------------------------------------------------------------------------------------------------
<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>
#include<boost/preprocessor/repetition.hpp>
#ifndef MAX_PHACTORIES
#define MAX_PHACTORIES 10
#endif
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 PARAM(z,Nb,data) boost::get<const boost::mpl::at_c<signature,
Nb >::type &>(theMap.find(theVarNames[Nb])->second)
#define INNER_RETRIVE_OBJECT(z,Nb,data)\
const{\template said:(const std::string &theKey,const ParameterMap& theMap)\
CheckMap(theMap);\
return boost::shared_ptr<BaseClass>(new DerivedClass(
BOOST_PP_ENUM(Nb,PARAM,~) ) \
);\
}
template
<
class BaseClass,
class DerivedClassclass PhRegistraublic 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=std::string(theVariableNames);
}Singleton said:::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;
BOOST_PP_REPEAT(MAX_PHACTORIES,INNER_RETRIVE_OBJECT,~)
private:
void CheckMap(const ParameterMap& theMap)const
{
assert(theMap.size()==ssize);
for(unsigned long i(0);i<ssize;++i)
assert(theMap.find(theVarNames)!=theMap.end());
}
std::string theVarNames[ssize];
};
#define PARAM_NAMES(n) n ,
static_cast<unsigned_long<sizeof(n)/sizeof(char*)> *>(0)
#undef MAX_PHACTORIES
#undef PARAM
#undef INNER_RETRIVE_OBJECT
#endif