RFC: various utility classes (factory, plugin, parser iterator)

Hi, as probably everyone in here, I have written many factory implementations and plugin managers in various projects, and decided to throw them all together into a set of template classes. My current approach looks like this: - class registrable base class for objects that can be registered somewhere - class registry : public registrable base class for objects that need to register some other objects. inherits from registrable, so there can be a registry of all registries (I think that can be made optional, but haven't found a compelling reason to do so). defines a set of abstract functions that registries need to implement (register/unregister of const/non-const objects), and static functions to register/unregister objects (by going through the list of registries and passing the object to each). - template<typename obj> class creator : public registrable base class for objects responsible for instantiating a concrete class and providing an object to match the factory argument against. - template<typename obj> class factory : public registry<creator<object_type>> factory. registers creators and can be asked to instantiate objects. - template<typename obj, typename stream> class parser base class for parsers. holds a stream reference and an object of "obj" type, defines some abstract functions and knows how to create proxy objects for the postincrement operator. - template<typename obj, typename stream> class parseiterator holds and owns a pointer to a parser<obj, stream> object, behaves like an iterator. can be instantiated on the stack, uses parameters to instantiate parser by using factory<parser<obj, stream>>. I believe these things are fairly generic and was surprised that they weren't already there. Would it make sense to add these to boost (after properly specifying and documenting them, of course)? Simon

On 6/2/05, Simon Richter <Simon.Richter@hogyros.de> wrote:
as probably everyone in here, I have written many factory implementations and plugin managers in various projects, and decided to throw them all together into a set of template classes.
There is a Factory implementation in the current review queue. The code is in the vault: http://boost-sandbox.sf.net/vault Look for factory3.zip. The implementation doesn't require inheritance from any particular base class. The factory objects are templated on an mpl::vector of types that they can create. The factory methods themselves are, I believe, pluggable at runtime.
- template<typename obj, typename stream> class parser
The purpose of your parser/parseiterator stuff eludes me. What is it for? Is it akin to Spirit? -- Caleb Epstein caleb dot epstein at gmail dot com

Hi, Caleb Epstein wrote:
There is a Factory implementation in the current review queue. The code is in the vault:
Thanks, I will have a look at it when I'm back home from work.
Look for factory3.zip. The implementation doesn't require inheritance from any particular base class.
The registrable/registry base classes are generic registries, as opposed to the more specific registry (that only takes creator object) the factory provides. I thought it might be a good idea to have that functionality split out into a separate class. The advantage of this approach is that there is a single entry point for any objects that need to be registered. If your program loads plug-in code from a DLL, and a plug-in provides a factory, creators for that factory can again be provided through the same entry point. By designing the plugin interface to contain a list of "registrable" objects that are passed to the (static) registry::register_object() function by the plugin loader, you can completely avoid any dependency of plugin code on dynamic symbols provided by the main program or other plugins, which makes programs more portable to platforms without a sane dynamic linker.
The factory objects are templated on an mpl::vector of types that they can create. The factory methods themselves are, I believe, pluggable at runtime.
Allowing multiple different objects to be created is a good thing. I will definitely enjoy reading that code. :-)
- template<typename obj, typename stream> class parser
The purpose of your parser/parseiterator stuff eludes me. What is it for? Is it akin to Spirit?
No, it is a wrapper around the actual parser that provides an input iterator interface (that can be constructed on the stack), but uses a factory to get the actual parser object (which is silently created on the heap). This makes sense if you have a (possibly abstract) base data type, several concrete data types and possibly multiple input formats. For example: class base { public: virtual int getData(void) = 0; }; class derived { public: virtual int getData(void); }; parseiterator<base> iter(std::cin, "derived-1"); parseiterator<base> end; This will get a "derived-1" parser from the parser factory (which is a global object), and have that object parse "derived" objects from stdin (how it does that is up to the virtual functions in the concrete parser class). When you dereference the iterator, you get a reference to a base object (as that is all that is known at compile time). New derived object types and parsers can then be added at runtime. Simon
participants (2)
-
Caleb Epstein
-
Simon Richter