From ceb4d4b5eaadf9162e202fd72320f06f6acf19f6 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 30 Oct 2009 00:32:26 +0100 Subject: [PATCH] reworked MultiFact passes unit test. Closes Ticket #376 --- src/lib/multifact-arg.hpp | 12 +++++++---- src/lib/multifact.hpp | 31 ++++++++++++++++++++++++--- tests/40components.tests | 7 ++++-- tests/lib/multifact-argument-test.cpp | 26 +++++++++------------- tests/lib/multifact-test.cpp | 2 +- 5 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/lib/multifact-arg.hpp b/src/lib/multifact-arg.hpp index 999b9542d..dfb452765 100644 --- a/src/lib/multifact-arg.hpp +++ b/src/lib/multifact-arg.hpp @@ -27,7 +27,12 @@ ** 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 + ** @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. ** ** @see multifact-argument-test.cpp ** @see query-resolver.cpp usage example @@ -63,7 +68,7 @@ namespace lib { * 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. + * fabrication functions to be installed into MultiFact. */ template< typename SIG , template class Wrapper @@ -82,7 +87,7 @@ namespace lib { /** - * Variant of MultiFact, accepting additional invocation argument. + * 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. @@ -98,7 +103,6 @@ namespace lib { : public MultiFact,ID,Wrapper> { typedef MultiFact,ID,Wrapper> _Base; - typedef typename _Base::Creator Creator; public: diff --git a/src/lib/multifact.hpp b/src/lib/multifact.hpp index 21656cbd9..6e77b5d6e 100644 --- a/src/lib/multifact.hpp +++ b/src/lib/multifact.hpp @@ -22,8 +22,30 @@ /** @file multifact.hpp ** Building blocks of a configurable factory, generating families of related objects. + ** Serving the "classical" factory situation: obtaining objects of various kinds, which + ** are related somehow (usually through an common interface). The creation of these + ** objects is non-trivial while number and exact parametrisation aren't known beforehand + ** and need to be figured out at runtime. Thus, a number of "fabrication lines" is set up, + ** to be selected on invocation through an ID (which may be symbolic, hashed or structural). ** - ** @todo WIP-WIP-WIP ... currently collecting various bits of implementation here. TICKET #277 + ** 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 needing various 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. ** ** @see multifact-test.cpp ** @see SingletonFactory @@ -48,6 +70,7 @@ namespace lib { namespace factory { + //////TODO: couldn't these wrappers be extracted into a separate header? /** * Dummy "wrapper", @@ -78,6 +101,8 @@ namespace lib { + + /** * Table of registered production functions for MultiFact. * Each stored function can be accessed by ID and is able @@ -193,7 +218,7 @@ namespace lib { /** * Convenience shortcut for automatically setting up * a production line, fabricating a singleton instance - * of the given target type (IMP) + * of the given implementation target type (IMP) */ template class Singleton @@ -217,7 +242,7 @@ namespace lib { /* === diagnostics === */ - + bool empty () const { return funcTable_.empty(); } bool contains (ID id) const { return funcTable_.contains (id); } }; diff --git a/tests/40components.tests b/tests/40components.tests index b46711e0c..a1013091e 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -284,7 +284,7 @@ return: 0 END -PLANNED "configurable Factory" MultiFact_test < #include -//#include #include @@ -36,19 +33,13 @@ namespace lib { namespace test{ -// using boost::lexical_cast; - using lib::test::showSizeof; -// using util::isSameObject; -// using util::isnil; -// using std::ostream; -// using std::string; using std::cout; using std::endl; using std::tr1::bind; using std::tr1::function; using std::tr1::placeholders::_1; + using lib::test::showSizeof; -// using lumiera::error::LUMIERA_ERROR_INVALID; namespace { // dummy fabrication function, creating wrapped numbers, controlled by an additional argument @@ -61,10 +52,10 @@ namespace test{ struct Num { int n_; }; /** dummy "factory" function to be invoked - * @return pointer to heap allocated product object + * @return pointer to heap allocated product object * @note this function needs to deliver the product in a form * which can be accepted by the concrete wrapper, which - * is going to be configured into the factory. + * is going to be configured into the factory. */ Num* fabricateNumberz (int base, int offset) @@ -82,6 +73,8 @@ namespace test{ , factory::BuildRefcountPtr // wrapper: manage product by smart-ptr > TestFactory; + // for reference: type of an equivalent dispatcher table... + typedef std::map > DispatcherMap; } @@ -103,13 +96,14 @@ namespace test{ class MultiFactArgument_test : public Test { void - run (Arg) + run (Arg) { TestFactory theFact; - theFact.defineProduction (ONE, bind (&fabricateNumberz, 1, _1)); - theFact.defineProduction (TWO, bind (&fabricateNumberz, 2, _1)); + theFact.defineProduction (ONE, bind (&fabricateNumberz, 1, _1 )); + theFact.defineProduction (TWO, bind (&fabricateNumberz, 2, _1 )); cout << showSizeof (theFact) << endl; + ASSERT (sizeof(theFact) == sizeof(DispatcherMap)); typedef TestFactory::Product PP; @@ -117,7 +111,7 @@ namespace test{ PP p2 = theFact(TWO, 3); ASSERT (1*2 == p1->n_); ASSERT (2*3 == p2->n_); - } + } }; diff --git a/tests/lib/multifact-test.cpp b/tests/lib/multifact-test.cpp index d2df7c886..2850c0ea0 100644 --- a/tests/lib/multifact-test.cpp +++ b/tests/lib/multifact-test.cpp @@ -97,7 +97,7 @@ namespace test{ /******************************************************************* * @test verify simple setup of the MultiFact template. - * Define a hierarchy of test dummy objects, such as to + * Define a hierarchy of test dummy objects, in order to * register them automatically for creation through a suitable * instantiation of MultiFact. Verify we get the correct product * when invoking this MultiFac flavour.