reworked MultiFact passes unit test. Closes Ticket #376
This commit is contained in:
parent
1dccd37c70
commit
ceb4d4b5ea
5 changed files with 52 additions and 26 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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_);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue