
Hi I'm not very familiar with Boost.Fusion, but as I'm currently working on adding support for function signatures to the abstract factory pattern (as per the current abstract_factory implementation in the vault, which builds on top of Loki), I'm in need of a sequence I can use to pack and forward constructor arguments so that there's no need to create n overloads for the creation policies' functions (where n is the number of arguments--needs just take a single non-polymorphic argument pack which can invoke an arbitrary n-argument functor). How does Fusion's sequence types deal with forwarding of references and such? My current implementation uses a custom, highly simplified argument packer which simply internally immutably stores and forwards arguments with types in the exact same form as they were specified in the function signature. Eg. for some_abstract_type*(int, const std::string&) it will store and forward an int by value and std::string by const reference. I am however not really sure if this is at all optimal, because it leaves a lot of room for error if a user simply forgets to specify some_really_large_type as a reference, in which case it will be copied several times before it reaches the actual construction code. But using all references internally seems to open the code up for the good old forwarding problems when dealing with rvalues (such as when doing factory.create<some_abstract_type*(int, const_std::string&)>(1234, my_string)), unless I'm mistaken. Ahh, dilemmas :) I'd be interested in hearing how you used Fusion for your purposes. I'm also very interested in input on how people would prefer an abstract factory to offer its functionality to users (as well as the design in general). Currently it allows code such as typedef abstract_factory< mpl::vector<abstract_foo, abstract_bar*(const std::string&), abstract_baz*()>
abstract_factory_t; ... typedef concrete_factory< abstract_factory_t , mpl::vector<foo_impl, prototype<>, baz_impl> concrete_factory_t;
which states that both abstract_foo and abstract_baz implementation objects should be created with their default constructors (abstract_baz's function signature is empty and thus their end-effect is the same), and that abstract_bar implementation objects should be created with a constructor taking in a const std::string&. When no function signature is present, specifying the type as a pointer is voluntary, as it is otherwise implicitly given as a result type. Concrete factories need not (and should not) specify any function signatures for their types, as these are already directly available in the abstract factory when a concrete type is matched up against its corresponding abstract type (based simply on their sequence positions). Is this an acceptable level of "magic", or will it cause confusion? The usage of MPL sequences in the external interfaces is something that is used for ease of implementation, but I suspect this is also something that many end-users will not necessarily be comfortable with. Some Boost.Preprocessor action should be enough to reduce this to abstract_factory<abstract_foo, abstract_bar....> et al, though. Creation is done through create<abstract-type>(params matching signature) member functions in the abstract factory type (as already shown): factory.create<some_abstract_type*(int, const_std::string&)>(1234, my_string); which seems a bit overly verbose. The need to specify the entire type in the template parameter is partially because I wanted to allow people to specify the same abstract base type several times, but with different constructor params (and mostly because it was the easiest, but let's casually pretend that wasn't the main reason). When I think about it, I'm not sure if this warrants the extra verbosity, however. If it's a requirement that no abstract base classes be identical, it should be possible to simply specify the abstract result-type itself, i.e. factory.create<some_abstract_type>(1234, my_string), and let the function figure out its parameters based on existing information present in the type hierarchy. This is once again a tradeoff nonverbosity<-->explicitness which has its pros and cons from both perspectives. As in Loki, due to their autogenerated class hierarchy abstract factories can be broken down into--and passed as--individual fields, decoupling the creation of single abstract types from their full factory type: void do_some_stuff(const abstract_factory_field<abstract_foo>& field) { std::auto_ptr<abstract_foo> p(field.create()); ... } ... do_some_stuff(my_concrete_factory); Note that the concrete type of abstract_bar is prototype<>, which means that a prototype object is used to create the new object, rather than the default operator new. Prototypes are internally stored as boost::shared_ptrs and assigned as follows: my_concrete_factory.prototype<abstract_bar*(const std::string&)>(new bar_impl(some_stuff)); with overloads for shared_ptr and auto_ptr. When create<...>(...) is invoked with a type that is implemented as a prototype, a clone operation is invoked on the stored object pointer. Currently, the passed construction-arguments are completely ignored. The clone operation, as well as what happens when there's no prototype stored is policy-specifyable (defaults to calling object->clone() and throwing an exception, respectively). Maik, I'll gladly add it to the sandbox, but I think I want to develop and clean up the code a bit further first, as well as extend the unit test coverage and try to get some proper BoostBook documentation up. Vicente, no worries, I simply hadn't looked closely enough at the existing functional factory implementation to judge whether or not mine offered the exact same functionality or not :) It seems the two should be able to live side by side, fulfilling different needs. Apologies for the somewhat fragmented reply. Best regards, Tor Brede Vekterli On Thu, Dec 4, 2008 at 6:03 PM, Stjepan Rajko <stjepan.rajko@gmail.com> wrote:
On Thu, Dec 4, 2008 at 4:35 AM, George van Venrooij <george.van.venrooij@organicvectory.com> wrote:
Have you take a look on the Boost.Factory library from Tobias Schwinger accepted the 2007-12-30. This library has not been yet added to Boost, you can get it from the Vault.
The Boost.Factory library seems to be something completely different. The boost-centric-factory-pattern-implementation library is definitely something I will try out as its implementation seems very complete and fits nicely into what I plan to do in the near future.
Indeed, Boost.Factory is a set of function object adaptors for dynamic or value construction (it is also referred to as Boost.Functional/Factory). Very useful in it's own right, but different from the library the OP mentioned.
I've used Boost.Functional/Factory in developing an object factory class that is much, much less developed than the mentioned boost-centric-factory-pattern-implementation - but in concert with Boost.Fusion, Boost.Factory made the implemenation rather straightforward. Perhaps the author of boost-centric-factory-pattern-implementation can find it useful to enhance his own library (which I also find interesting and would like to take a closer look when I get some time).
Stjepan _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost