reworked MultiFact passes unit test. Closes Ticket #376

This commit is contained in:
Fischlurch 2009-10-30 00:32:26 +01:00
parent 1dccd37c70
commit ceb4d4b5ea
5 changed files with 52 additions and 26 deletions

View file

@ -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> 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<function<ELM(ARG)>,ID,Wrapper>
{
typedef MultiFact<function<ELM(ARG)>,ID,Wrapper> _Base;
typedef typename _Base::Creator Creator;
public:

View file

@ -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 IMP>
class Singleton
@ -217,7 +242,7 @@ namespace lib {
/* === diagnostics === */
bool empty () const { return funcTable_.empty(); }
bool contains (ID id) const { return funcTable_.contains (id); }
};

View file

@ -284,7 +284,7 @@ return: 0
END
PLANNED "configurable Factory" MultiFact_test <<END
TEST "configurable Factory" MultiFact_test <<END
out: Impl-1
out: Impl-2
out: Impl-3
@ -294,7 +294,10 @@ return: 0
END
PLANNED "Factory argument handling" MultiFactArgument_test <<END
TEST "Factory argument handling" MultiFactArgument_test <<END
out: sizeof\( .+MultiFact.+Num.+prodID.+BuildRefcountPtr.+ \) =
out: fabricate\(1, 2\)
out: fabricate\(2, 3\)
return: 0
END

View file

@ -24,11 +24,8 @@
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/multifact-arg.hpp"
//#include "lib/util.hpp"
//#include <boost/lexical_cast.hpp>
#include <iostream>
//#include <string>
#include <tr1/functional>
@ -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<prodID, function<Num(int)> > 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_);
}
}
};

View file

@ -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.