diff --git a/src/lib/multifact-arg.hpp b/src/lib/multifact-arg.hpp index c0c779c60..999b9542d 100644 --- a/src/lib/multifact-arg.hpp +++ b/src/lib/multifact-arg.hpp @@ -41,7 +41,7 @@ #include "lib/multifact.hpp" -#include +#include "lib/meta/function.hpp" @@ -49,42 +49,63 @@ namespace lib { namespace factory { + using lumiera::typelist::Types; + using lumiera::typelist::FunctionSignature; + using lumiera::typelist::FunctionTypedef; using std::tr1::function; - template - struct FabTraits + /** + * Extended MultiFact configuration for arbitrary fabrication functions. + * Contrary to the (simple) standard case, such fabrication functions + * take additional arguments on each invocation. These arguments need + * to be passed through by MultiFact. Moreover, the actual Wrapper + * used may require these fabrication functions to deliver their + * product in a specific form, e.g. as pointer or reference. + * Thus, we have to re-build the actual signature of the + * fabrication functions to be installed into MultiFact. + */ + template< typename SIG + , template class Wrapper + > + struct FabWiring, Wrapper> + : Wrapper >::Ret> { - typedef TY RawProduct; - typedef RawProduct FabSig(ARG); - typedef ARG Argument; + typedef typename FunctionSignature >::Args Args; + typedef typename FunctionSignature >::Ret Element; + typedef typename Wrapper::PType WrappedProduct; + typedef typename Wrapper::RType FabProduct; + typedef typename FunctionTypedef::Sig SIG_Fab; }; /** - * Variant of MultiFact, selecting a creator function by ID - * with the ability to pass additional argument(s) to this - * creator function on invocation. - * TODO type comment + * Variant of MultiFact, accepting additional invocation argument. + * Similar to the (simple) standard case, this MultiFact specialisation + * allows to install suitable fabrication function(s) at runtime and + * will select the function to use on invocation based on the given ID. + * One additional argument will be passed on to this function. + * @todo with a bit more metaprogramming it would be possible to + * accept multiple arguments; maybe we'll need this later on. */ - template< typename SIG + template< typename ELM, typename ARG , typename ID , template class Wrapper > - class MultiFact, ID, Wrapper> - : public MultiFact + class MultiFact + : public MultiFact,ID,Wrapper> { - typedef MultiFact _Base; - typedef typename FabTraits::Argument ArgType; + typedef MultiFact,ID,Wrapper> _Base; - typedef typename _Base::Product Product; typedef typename _Base::Creator Creator; public: + typedef typename _Base::Product Product; + Product - operator() (ID const& id, ArgType arg) + operator() (ID const& id, ARG arg) { Creator& func = selectProducer (id); return wrap (func(arg)); diff --git a/src/lib/multifact.hpp b/src/lib/multifact.hpp index fee171b96..21656cbd9 100644 --- a/src/lib/multifact.hpp +++ b/src/lib/multifact.hpp @@ -78,25 +78,16 @@ namespace lib { - template - struct FabTraits - { - typedef TY RawProduct; - typedef RawProduct FabSig(void); - }; - - - /** * Table of registered production functions for MultiFact. * Each stored function can be accessed by ID and is able - * to fabricate a specific object, which is assignable to TY + * to fabricate a specific object, which is assignable to + * the nominal target type in the MultiFact definition. */ - template + template struct Fab { - typedef typename FabTraits::FabSig Signature; - typedef std::tr1::function FactoryFunc; + typedef std::tr1::function FactoryFunc; FactoryFunc& @@ -126,6 +117,23 @@ namespace lib { + /** + * @internal configuration of the elements + * to be combined into a MultiFact instance + */ + template< typename TY + , template class Wrapper + > + struct FabWiring + : Wrapper + { + typedef typename Wrapper::PType WrappedProduct; + typedef typename Wrapper::RType FabProduct; + typedef FabProduct SIG_Fab(void); + }; + + + /** * Factory for creating a family of objects by ID. * The actual factory functions are to be installed @@ -141,20 +149,17 @@ namespace lib { , template class Wrapper > class MultiFact - : Wrapper::RawProduct> + : public FabWiring { - typedef Wrapper::RawProduct> _Wrap; - typedef typename FabTraits::RawProduct RawType; - typedef typename _Wrap::PType WrappedProduct; - typedef typename _Wrap::RType FabProduct; - typedef Fab _Fab; + typedef FabWiring _Conf; + typedef typename _Conf::SIG_Fab SIG_Fab; + typedef Fab _Fab; _Fab funcTable_; protected: typedef typename _Fab::FactoryFunc Creator; - typedef WrappedProduct Product; Creator& selectProducer (ID const& id) @@ -164,6 +169,8 @@ namespace lib { public: + typedef typename _Conf::WrappedProduct Product; + Product operator() (ID const& id) { diff --git a/tests/lib/multifact-argument-test.cpp b/tests/lib/multifact-argument-test.cpp index e3e6a7b09..5258696b1 100644 --- a/tests/lib/multifact-argument-test.cpp +++ b/tests/lib/multifact-argument-test.cpp @@ -77,7 +77,7 @@ namespace test{ /** the factory instantiation used for this test */ - typedef factory::MultiFact< function // nominal signature of fabrication + typedef factory::MultiFact< Num(int) // nominal signature of fabrication , prodID // select factory function by prodID , factory::BuildRefcountPtr // wrapper: manage product by smart-ptr > TestFactory;