diff --git a/src/lib/multifact-arg.hpp b/src/lib/multifact-arg.hpp new file mode 100644 index 000000000..fda2d087a --- /dev/null +++ b/src/lib/multifact-arg.hpp @@ -0,0 +1,100 @@ +/* + MULTIFACT-ARG.hpp - variant of family-of-object factory, accepting fabrication arguments + + Copyright (C) Lumiera.org + 2009, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file multifact.hpp + ** Extension allowing the MultiFact to pass arguments to the fabrication. + ** This extension is implemented by template specialisations and thus kicks in + ** when specifying a function \em signature as factory "product type". The resulting + ** factory class exposes a function call operator matching this signature, additionally + ** expecting the ID (to select the specific fabrication function) as first parameter. + ** + ** @todo WIP-WIP-WIP ... does this work out as intended?? TICKET #377 + ** + ** @see multifact-argument-test.cpp + ** @see query-resolver.cpp usage example + ** @see multifact.hpp standard case + */ + + +#ifndef LIB_MULTIFACT_ARG_H +#define LIB_MULTIFACT_ARG_H + + +#include "lib/multifact.hpp" + + + +namespace lib { + namespace factory { + + + using std::tr1::function; + + + template + struct FabTraits + { + typedef TY RawProduct; + typedef RawProduct FacSig(ARG); + typedef ARG Argument; + }; + + + + + /** + * 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 + */ + template< typename SIG, + , typename ID + , template class Wrapper + > + class MultiFact, ID, Wrapper> + : public MultiFact + { + + typedef typename FabTraits::Argument ArgType; + + public: + Product + operator() (ID const& id, ArgType arg) + { + Creator& func = selectProducer (id); + return wrap (func(arg)); + } + + }; + + + + } // namespace factory + + + + // TODO is there some suitable standard configuration we could provide here?? + + +} // namespace lib +#endif diff --git a/src/lib/multifact.hpp b/src/lib/multifact.hpp index 1e15949eb..37ff84d4f 100644 --- a/src/lib/multifact.hpp +++ b/src/lib/multifact.hpp @@ -25,6 +25,7 @@ ** ** @todo WIP-WIP-WIP ... currently collecting various bits of implementation here. TICKET #277 ** + ** @see multifact-test.cpp ** @see SingletonFactory ** @see lib::factory::Factory */ @@ -60,6 +61,15 @@ namespace lib { }; + template + struct FabTraits + { + typedef TY RawProduct; + typedef RawProduct FacSig(void); + }; + + + /** * Table of registered production functions for MultiFact. * Each stored function can be accessed by ID and is able @@ -68,12 +78,12 @@ namespace lib { template struct Fab { - typedef TY& RawProduct; - typedef std::tr1::function FactoryFunc; + typedef typename FabTraits::FacSig Signature; + typedef std::tr1::function FactoryFunc; FactoryFunc& - select (ID id) + select (ID const& id) { if (!contains (id)) throw lumiera::error::Invalid("unknown factory product requested."); @@ -82,7 +92,7 @@ namespace lib { } void - defineProduction (ID id, FactoryFunc fun) + defineProduction (ID const& id, FactoryFunc fun) { producerTable_[id] = fun; } @@ -114,20 +124,30 @@ namespace lib { , template class Wrapper > class MultiFact - : Wrapper + : Wrapper::RawProduct> { typedef Fab _Fab; - typedef typename _Fab::FactoryFunc Creator; - typedef typename Wrapper::PType Product; _Fab funcTable_; + protected: + typedef typename FabTraits::RawProduct RawType; + typedef typename Wrapper::PType Product; + typedef typename _Fab::FactoryFunc Creator; + + + Creator& + selectProducer (ID const& id) + { + return funcTable_.select(id); + } + public: Product - operator() (ID id) + operator() (ID const& id) { - Creator& func = funcTable_.select(id); + Creator& func = selectProducer (id); return wrap (func()); } diff --git a/tests/lib/multifact-argument-test.cpp b/tests/lib/multifact-argument-test.cpp index 462f76ff1..c83f36061 100644 --- a/tests/lib/multifact-argument-test.cpp +++ b/tests/lib/multifact-argument-test.cpp @@ -102,7 +102,7 @@ namespace test{ cout << showSizeof (theFact) << endl; - typedef TestFactory::PType PP; + typedef TestFactory::Product PP; DummyID id1 = {ONE, 2}; DummyID id1 = {TWO, 3};