From 9a5d9873c8ff343a1d44cf0e28bd7eacada43f80 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 14 Sep 2014 22:38:58 +0200 Subject: [PATCH] WIP: prepare switch to the reworked MultiFac implementation #388 --- src/lib/multifact-arg.hpp | 138 ------------------- src/lib/multifact.hpp | 277 -------------------------------------- src/lib/muttifac.hpp | 8 +- 3 files changed, 4 insertions(+), 419 deletions(-) delete mode 100644 src/lib/multifact-arg.hpp delete mode 100644 src/lib/multifact.hpp diff --git a/src/lib/multifact-arg.hpp b/src/lib/multifact-arg.hpp deleted file mode 100644 index fb6cd6082..000000000 --- a/src/lib/multifact-arg.hpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - 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-arg.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 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. - ** - ** @note the function signature used for this variant of MultiFact should specify - ** the raw/base (interface) type of the produced objects as a return type. - ** Depending on the used wrapper, the actual fabrication functions indeed - ** should yield the product in a form suitable to be accepted by the - ** wrapper. E.g., when building smart-ptrs, the fabrication function - ** should actually deliver a raw pointer to a heap allocated object. - ** @todo still way to convoluted design. We can do better //////////TICKET #388 - ** - ** @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" - -#include "lib/meta/function.hpp" - - - -namespace lib { - namespace factory { - - - using lib::meta::Types; - using lib::meta::FunctionSignature; - using lib::meta::FunctionTypedef; - using std::function; - - - /** - * 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 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, accepting an 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 ELM, typename ARG - , typename ID - , template class Wrapper - > - class MultiFact - : public MultiFact,ID,Wrapper> - { - typedef MultiFact,ID,Wrapper> _Base; - typedef typename _Base::Creator Creator; - - public: - typedef typename _Base::Product Product; - - Product - operator() (ID const& id, ARG arg) - { - Creator& func = this->selectProducer (id); - return this->wrap (func(arg)); - } - - Product - invokeFactory (ID const& id, ARG arg) ///< alias for the function operator - { - return this->operator() (id, 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 deleted file mode 100644 index 6af26e8a3..000000000 --- a/src/lib/multifact.hpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - MULTIFACT.hpp - flexible family-of-object factory template - - 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 - ** Framework for building a configurable factory, to generate families of related objects. - ** These building blocks are targeted towards the "classical" factory situation: obtaining - ** objects of various kinds, which are related somehow (usually through an common interface). - ** The creation of these objects might be non-trivial, while the number of flavours to be - ** produced and the exact parametrisation isn't known beforehand and needs to be figured out - ** at runtime. As a solution, thus a number of "fabrication lines" is set up, to be selected - ** on invocation through an ID (which may be symbolic, hashed or structural). - ** - ** Usually, the issue of object and storage management is closely related, while it is - ** desirable to keep the object production logic clean of these rather technical concerns. - ** The implementation built here separates the latter into a policy template invoked as a - ** \em wrapper, accepting the raw product and either registering it, taking ownership, clone - ** it or use it for more involved wiring. Obviously, the product generated by the installed - ** "fabrication lines" needs to be delivered in a form acceptable by the concrete wrapper; - ** mismatch will be spotted by the compiler on registration of the respective fabrication - ** function. - ** - ** \par Singleton generation - ** For the very common situation of building a family of singleton objects, accessible by ID, - ** there is a convenience shortcut: The nested MultiFact::Singleton template can be instantiated - ** within the context providing the objects (usually a static context). In itself a lib::Singleton - ** factory, it automatically registers the singleton access function as "fabrication" function - ** into a suitable MultiFact instance passed in as ctor parameter. - ** - ** @note there is an extension header, multifact-arg.hpp, which provides template specialisations - ** for the special case when the fabrication functions need additional invocation arguments. - ** @todo still way to convoluted design. We can do better //////////TICKET #388 - ** - ** @see multifact-test.cpp - ** @see multifact-argument-test.cpp - ** @see SingletonFactory - */ - - -#ifndef LIB_MULTIFACT_H -#define LIB_MULTIFACT_H - - -#include "lib/error.hpp" -#include "lib/depend.hpp" -#include "util.hpp" - -#include -#include -#include - - - -namespace lib { - namespace factory { - - // Helpers to wrap the factory's product - - /** - * Dummy "wrapper", - * just returning a target-ref - */ - template - struct PassReference - { - typedef TAR& RType; - typedef TAR& PType; - - PType wrap (RType object) { return object; } - }; - - - /** - * Wrapper taking ownership, - * by wrapping into smart-ptr - */ - template - struct BuildRefcountPtr - { - typedef TAR* RType; - typedef std::shared_ptr PType; - - PType wrap (RType ptr) { return PType{ptr}; } - }; - - - - - - /** - * 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 - * the nominal target type in the MultiFact definition. - */ - template - struct Fab - { - typedef std::function FactoryFunc; - - - FactoryFunc& - select (ID const& id) - { - if (!contains (id)) - throw lumiera::error::Invalid("unknown factory product requested."); - - return producerTable_[id]; - } - - void - defineProduction (ID const& id, FactoryFunc fun) - { - producerTable_[id] = fun; - } - - - /* === diagnostics === */ - - bool empty () const { return producerTable_.empty(); } - bool contains (ID id) const { return util::contains (producerTable_,id); } - - private: - std::map producerTable_; - }; - - - - /** - * @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 - * from the usage site through calls to #defineProduction . - * Each generated object will be treated by the Wrapper template, - * allowing for the generation of smart-ptrs. The embedded class - * Singleton allows to build a family of singleton objects; it is - * to be instantiated at the call site and acts as singleton factory, - * accessible through a MultiFact instance as frontend. - */ - template< typename TY - , typename ID - , template class Wrapper - > - class MultiFact - : public FabWiring - { - typedef FabWiring _Conf; - typedef typename _Conf::SIG_Fab SIG_Fab; - typedef Fab _Fab; - - _Fab funcTable_; - - - protected: - typedef typename _Fab::FactoryFunc Creator; - - Creator& - selectProducer (ID const& id) - { - return funcTable_.select(id); - } - - - public: - typedef typename _Conf::WrappedProduct Product; - - Product - operator() (ID const& id) - { - Creator& func = this->selectProducer (id); - return this->wrap (func()); - } - - Product - invokeFactory (ID const& id) ///< alias for the function operator - { - return this->operator() (id); - } - - - /** to set up a production line, - * associated with a specific ID - */ - template - void - defineProduction (ID id, FUNC fun) - { - funcTable_.defineProduction (id, fun); - } - - - /** - * Convenience shortcut for automatically setting up - * a production line, to fabricate a singleton instance - * of the given implementation target type (IMP) - */ - template - class Singleton - : lib::Depend - { - typedef lib::Depend SingFac; - - Creator - createSingleton_accessFunction() - { - return std::bind (&SingFac::operator() - , static_cast(this)); - } - - public: - Singleton (MultiFact& factory, ID id) - { - factory.defineProduction(id, createSingleton_accessFunction()); - } - }; - - - /* === diagnostics === */ - - bool empty () const { return funcTable_.empty(); } - bool contains (ID id) const { return funcTable_.contains (id); } - }; - - - - } // namespace factory - - - - /** - * Standard configuration of the family-of-object factory - * @todo this is rather guesswork... find out what the best and most used configuration could be.... - */ - template< typename TY - , typename ID - > - class MultiFact - : public factory::MultiFact - { }; - - -} // namespace lib -#endif diff --git a/src/lib/muttifac.hpp b/src/lib/muttifac.hpp index 13134c390..c63d31fa2 100644 --- a/src/lib/muttifac.hpp +++ b/src/lib/muttifac.hpp @@ -60,8 +60,8 @@ */ -#ifndef LIB_MUTTIFACT_H -#define LIB_MUTTIFACT_H +#ifndef LIB_MULTIFACT_H +#define LIB_MULTIFACT_H #include "lib/error.hpp" @@ -261,7 +261,7 @@ namespace lib { , typename ID , template class Wrapper = PassAsIs > - class MuttiFac + class MultiFact : public FabConfig::WrapFunctor { using _Conf = FabConfig; @@ -344,7 +344,7 @@ namespace lib { } public: - Singleton (MuttiFac& factory, ID id) + Singleton (MultiFact& factory, ID id) { factory.defineProduction(id, createSingleton_accessFunction()); }