#include <openbabel/babelconfig.h>
Include dependency graph for pluginiter.h:
This graph shows which files directly or indirectly include this file:
Go to the source code of this file.
Namespaces | |
namespace | OpenBabel |
Classes | |
class | PluginIter |
Template class used to simplify dynamic classes discovered at runtime. More... | |
Defines | |
#define | FOR_EACH(plugintype, f) for(PluginIter<plugintype>& f=plugintype::Iter(); f; ++f ) |
#define | MAKE_PLUGIN(BaseClass) |
The code in this file makes it easy to make 'plugin' classes. These classes are derived from an abstract base class, like OBFingerprint. The derived classes ('sub-types' like fingerprint2) usually have a single instance. Plugin classes are only discovered at runtime, so no existing code needs to be changed when adding a new derived class. In some builds the new code can be added or removed by just moving a DLL or so file.
1) In the header file for YourBaseClass. Make sure to include the plugininter.h header and in the definition of YourBaseClass add the MAKE_PLUGIN macro and a pure virtual function Description().
#include <openbabel/plugininter.h> class YourBaseClass { MAKE_PLUGIN(YourBaseClass) virtual string Description()=0; ...rest of implementation, probably involving virtual functions redefined in the sub-type classes };
2) Declare each sub-type in a class derived from the base class and give it a constructor which calls the base class constructor as shown:
class YourSubType1 : public YourBaseClass { public: YourSubtype1(string ID, bool IsDefault=false) : YourBaseClass(ID, IsDefault){} virtual string Description() { return "A short useful description";}; ...rest ofimplementation };
3) Declare a global instance of the sub-type class which specifies its ID. and, optionally, whether it is to be regarded as the default type of YourBaseClass.
YourSubType1 theType1("FP2",true);
4) The following functions are available: YourBaseClass* YourBaseClass::FindType(const string& ID); YourBaseClass* YourBaseClass::FindDefaultType();
PluginIter<YourBaseClass>& YourBaseClass::Iter(); This returns an object which looks like a pointer to YourBaseClass when used with * or -> . It initially points to the first sub-type and can be subsequently made to point to all the rest using the prefix ++ operator. When tested as a bool it returns false when there are no more subtypes.
But the easiest way to access all the subtypes is to use the macro FOR_EACH. For example to print out all the subtypes with their descriptions:
FOR_EACH(YourBaseClass, iter) { cout << iter.ID() << ' ' << iter->Description() << endl; }
MAKE_PLUGIN(YourBaseClass) inserts the following code into YourBaseClass:
//This static function returns a reference to the PluginIter object, //which contains the map of sub-types and the default sub-type. //Because it is a static local variable it is constructed only once. //This avoids the "static initialization order fiasco", //see www.parashift.com/c++-faq-lite/. //Every time this function is used it sets the iterator to the start of the map. static PluginIter<YourBaseClass>& Iter() { static PluginIter<YourBaseClass>* p = NULL; if(!p) p = new PluginIter<YourBaseClass>*; p->ToStart(); return *p; } Each sub-type is registered from its constructor as it is loaded, which could be at program start up, or later. YourBaseClass(std::string ID, bool IsDefault=false) { Iter().Register(this, ID, IsDefault); } //The following just pass on the work to the PluginIter object. YourBaseClass* FindDefaultType(){ return Iter().FindDefault();} YourBaseClass* FindType(const string& ID){ return Iter().FindType(const string& ID);}
#define FOR_EACH | ( | plugintype, | |||
f | ) | for(PluginIter<plugintype>& f=plugintype::Iter(); f; ++f ) |
#define MAKE_PLUGIN | ( | BaseClass | ) |
Value:
public:\ BaseClass(std::string ID, bool IsDefault=false)\ {Iter().Register(this, ID, IsDefault);}\ static PluginIter<BaseClass>& Iter()\ {static PluginIter<BaseClass>* p = NULL;\ if(!p) p = new PluginIter<BaseClass>;\ p->ToStart();\ return *p;}\ static BaseClass* FindDefaultType(){ return Iter().FindDefaultType();}\ static BaseClass* FindType(const std::string& ID){ return Iter().FindType(ID);}