Boost logo

Boost :

Subject: [boost] Re : typeof or similar
From: Pierre Morcello (pmorcell-cppfrance_at_[hidden])
Date: 2010-02-23 16:17:31


Hello, Steffen Roeber wrote : >>>My preferred way would be something like a factory: >>>> [...] >>>>>Base *derived = Factory::createDerived<sameAsBase> (base); I am not convinced you are on the good mailing list ? Anyway, I think I can give you that. I wrote it for you ^^. First the .h, then an example of use. //////////////////// ////////////////////.H //////////////////// #include <map> #include <boost/shared_ptr.hpp> #include <memory> #define nullptr NULL; typedef int SomeClassId; // Wichtig : you will need to specialise extractId for each of your template types. // make sure to send a different id for each class. template <class T> struct ExtractId { static SomeClassId extractTypeId() { return -1; } }; // I retake your example class Base { public: virtual ~Base(){} virtual SomeClassId getTypeId(){throw;} }; template <class T> class BaseT : public Base { virtual ~BaseT(){} virtual SomeClassId getTypeId(){return ExtractId<T>::extractTypeId();} }; // this was unclear for me if you wanted that Derived derives from Base or not. // I consider that what you wrote ("Base *derived = base->createDerived(); //base is a Base *") // implies that Derived inherits from Base after all. template <class T> class Derived : public Base { virtual ~Derived(){} virtual SomeClassId getTypeId(){return ExtractId<T>::extractTypeId();} }; // a base factory class, needed for polymorphism. class OneTypeFactory { public: virtual ~OneTypeFactory(){} virtual Base* createDerived(){throw;} virtual SomeClassId getTypeId(){throw;} }; template <class T> class InheritedFactory : public OneTypeFactory { public: virtual ~InheritedFactory(){} virtual Base* createDerived(){ return new Derived<T>();} virtual SomeClassId getTypeId(){ return ExtractId<T>::extractTypeId();} }; class AllFactories { public: // you can make it some singleton if you want... (e.g static std::auto_ptr<AllFactories> sData;) AllFactories():mAllFactories(){} // to register the factories => insert them in the mAllFactories. void registerFactory(boost::shared_ptr<OneTypeFactory> pFactory) { mAllFactories.insert(std::make_pair(pFactory->getTypeId(), pFactory)); } // create a derived from b, using the same template type. Base* createDerived(Base* pBase) { Base* lResult = nullptr; if(pBase) { lResult = createDerived(pBase->getTypeId()); } return lResult; } private: Base* createDerived(SomeClassId pId) { Base* lResult = nullptr; // if found in mAllFactories, ask the corresponding factory to create // the derived... TFactories::iterator lFound = mAllFactories.find(pId); if(lFound != mAllFactories.end()) { lResult = (lFound->second)->createDerived(); } return lResult; } typedef std::map<SomeClassId, boost::shared_ptr<OneTypeFactory> > TFactories; TFactories mAllFactories; }; // and then, at the beginning of the program, you can register factories for your types. // and later you can call : AllFactories::getSingleton()->createDerived(base); // base is a Base* //////////////////// ////////////////////example of use in .cpp //////////////////// #include "factoryforfun.h" // I write a little macro to help the copy/paste job. // of course, use typedef or anything (boost.preprocessor sequence) to // avoid ',' in the macro... // value, corresponding type. #define MACRO_WRITEEXTRACTID(X,Y) \ template <> \ struct ExtractId<Y> \ { \ static SomeClassId extractTypeId() \ { \ return X; \ } \ }; MACRO_WRITEEXTRACTID(1, int) MACRO_WRITEEXTRACTID(2, double) MACRO_WRITEEXTRACTID(3, char) // its also possible to only register the type with a template // at the beginning of the program, and make a counter increase, // etc... int main(void) { // program begins AllFactories lAllFactories; lAllFactories.registerFactory(boost::shared_ptr<OneTypeFactory>(new InheritedFactory<int>())); lAllFactories.registerFactory(boost::shared_ptr<OneTypeFactory>(new InheritedFactory<double>())); lAllFactories.registerFactory(boost::shared_ptr<OneTypeFactory>(new InheritedFactory<char>())); // later... // I create my pointers std::auto_ptr<Base> lBaseT_Char (new BaseT<char>() ); std::auto_ptr<Base> lBaseT_Double (new BaseT<double>()); std::auto_ptr<Base> lBaseT_Int (new BaseT<int>() ); // I create the derived std::auto_ptr<Base> lShouldBeDerived_Char; std::auto_ptr<Base> lShouldBeDerived_Double; std::auto_ptr<Base> lShouldBeDerived_Int; if(true) { //pseudo - dynamic branching creation. lShouldBeDerived_Char = std::auto_ptr<Base>(lAllFactories.createDerived(lBaseT_Char.get())); lShouldBeDerived_Double = std::auto_ptr<Base>(lAllFactories.createDerived(lBaseT_Double.get())); lShouldBeDerived_Int = std::auto_ptr<Base>(lAllFactories.createDerived(lBaseT_Int.get())); } // works like a charm : they are all of the good type. //////////////////// ////////////////////end. //////////////////// Hope you like it ? Best regards, Pierre Morcello


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk