
Roland Schwarz wrote:
What if I write:
shape* ps2 = dynamic_new<shape>("circle", 20);
?
Since I am using a template function as a type generator and tipeid().name() in turn this will deduce a function requiring an int for the ctor. Since only double has been registered in the example program your example will not work. (It will give a 0 -pointer at runtime.)
Yes, that's what I though. In other words, your implementation is dynamically checked. (This is consistent with the name 'dynamic_new', BTW).
Please note that my implementation is not very smart and could be improved by someone more knowledgeable than me. Perhaps it is not so hard to add support for automatic type conversion too?
The problem is that need either: 1. A statically available list of overloaded functions, so that compiler can do the overload resolution. 2. Boost.Overload library which can do it using typeid or some other metedata. Such library does not exist, though :-(
But then my implementation fits entirely (almost) on two sheets of paper.
Mine too ;-) template<class BasePlugin> struct virtual_constructors { typedef mpl::list<mpl::list<> > type; };
Altough I have not a very good knowledge of the mpl lib right now, this looks very interseting to me.
The disadvantage is that you need to explicitly instantiate 'virtual_construct',
Hmm, I cannot see how I ever could do away with this instatiation. Or do you mean it should better be done implicitely?
Well, I mean that unlike your solution, you can query for specific constructor signature. Using plugins as example, even if specific plugin class has additional constructors, it's not possible to call them via generic interface.
but then you get static checking. For example, a plugin can't forget to define a required constructor.
I also considered this syntax: struct virtual_constructors<Weapon> { typedef mpl::list<ctor (std::string), ctor (std::string, int)> .....
where 'ctor' is auxillary struct, but maybe it's too smart, haven't decided yet.
I am not entirely sure, if you intend this struct as external to your class or as a member?
External template that the user has to specialize.
Most likely I did not yet get the full picture and my question might seem somewhat blurry. Could you post a little example that exhibits the user interface?
Sure. I'll expand the previous example. You have a class which is intended to be "base" for plugins. So, you can load dynamic library, and ask it to create a class, giving name (string) and a set of parameter. You can back a pointer to "base". Here's definition of the base class: class Weapon { public: virtual void fire() = 0; virtual ~Weapon() {} }; Second, it's needed to define a set of constructor parameter that each plugin should support: namespace boost { namespace plugin { template<> struct virtual_constructors<Weapon> { typedef mpl::list<mpl::list<std::string>, mpl::list<std::string, int> > type; }; The machinery used to create plugins is somewhat complex. I can describe the logic used for plugins, but to save space will describe only part which is usable everywhere. A class can be registred with: std::map<std::string, boost::any> classes; static boost::plugin::concrete_factory<Weapon, Missile> cf; boost::plugin::abstract_factory<Weapon>* w = &cf; classes.insert(std::make_pair("missile", w)); The 'abstract_factory' has a virtual 'create' method for each signature declared by 'virtual_constructors'. The 'concrete_factory' class defines those methods for a specific class to be created. The above map can be used as: // Want to create a weapon by name std::any f = classes["missile"]; any_cast<abstract_factory<Weapon>* >(f)->create("foo", 10); The use of any allows to store completely different factories in one map, and any_cast will verify that you're using the correct type. In Boost.Plugins the above code is hidden under higher-level interface, like: BOOST_EXPORT_PLUGIN(Weapon, Missile, "Missile"); BOOST_EXPORT_PLUGIN_LIST(); but it's just for convenience. - Volodya