MultiFact: implement the last and most complex usage case

the use of a custom finisihing functor, which is applied
to any generated product. This can be used for registration,
memory management or similar framework aspects
This commit is contained in:
Fischlurch 2014-09-14 22:25:12 +02:00
parent 932d49fd95
commit 591e6d9775
2 changed files with 83 additions and 10 deletions

View file

@ -41,9 +41,9 @@
** \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.
** within the context providing the objects (usually a static context). In itself a lib::Depend
** singleton factory, it automatically registers the singleton access function as "fabrication"
** function into a suitable MultiFact instance passed in as ctor parameter.
**
** @remarks this is the second attempt at building a skeleton of the core factory mechanics.
** The first attempt was pre-C++11, relied on partial specialisations and was hard to
@ -55,7 +55,7 @@
** wrapper invoke the fabrication function and handle the result properly.
**
** @see multifact-test.cpp
** @see multifact-argument-test.cpp
** @see multifact-singleton-test.cpp
** @see SingletonFactory
*/
@ -106,22 +106,64 @@ namespace lib {
* Wrapper taking ownership,
* by wrapping into smart-ptr
*/
template<typename TAR>
template<typename RAW>
struct BuildRefcountPtr
{
using RawType = typename std::remove_pointer<TAR>::type;
using RawType = typename std::remove_pointer<RAW>::type;
using BareType = RawType *;
using ResultType = std::shared_ptr<RawType>;
template<class FUN, typename... ARGS>
ResultType
wrap (FUN create, ARGS... args) noexcept
wrap (FUN create, ARGS... args)
{
return ResultType (create(args...));
}
};
/**
* Policy: use a custom functor
* to finish the generated product
* @remarks the nested structure allows to define
* both the raw type and the wrapped type.
* On instantiation of the MultiFact, pass
* the nested Wrapper struct template param.
* @warning the RAW type must match the result type
* of the MultiFac SIG. Beware of passing
* references or pointers to local data.
*/
template<typename TAR>
struct Build
{
template<typename RAW>
struct Wrapper
{
using RawType = RAW;
using BareType = RAW;
using ResultType = TAR;
using WrapFunc = std::function<ResultType(BareType)>;
void
defineFinalWrapper (WrapFunc&& fun)
{
this->wrapper_ = fun;
}
template<class FUN, typename... ARGS>
ResultType
wrap (FUN create, ARGS&&... args)
{
return wrapper_(std::forward<BareType> (create(args...)));
}
private:
WrapFunc wrapper_;
};
};
@ -203,6 +245,8 @@ namespace lib {
/* === Main type === */
/**
* Factory for creating a family of objects by ID.
* The actual factory functions are to be installed
@ -218,7 +262,7 @@ namespace lib {
, template<class> class Wrapper = PassAsIs
>
class MuttiFac
: FabConfig<SIG,Wrapper>::WrapFunctor
: public FabConfig<SIG,Wrapper>::WrapFunctor
{
using _Conf = FabConfig<SIG,Wrapper>;
using SIG_Fab = typename _Conf::SIG_Fab;

View file

@ -209,7 +209,7 @@ namespace test{
TestFactory theFact;
// the first "production line" is wired to a free function
// set up the "production lines" by lambda
theFact.defineProduction (ONE, [] { return new Implementation<ONE>; });
theFact.defineProduction (TWO, [] { return new Implementation<TWO>; });
theFact.defineProduction (THR, [] { return new Implementation<THR>; });
@ -247,7 +247,7 @@ namespace test{
TestFactory theFact;
// the first "production line" is wired to a free function
// set up the "production lines"
theFact.defineProduction (ONE, [](string ) { return new Implementation<ONE>; });
theFact.defineProduction (TWO, [](string ) { return new Implementation<TWO>("X"); });
theFact.defineProduction (THR, [](string id) { return new Implementation<THR>(id); });
@ -287,6 +287,35 @@ namespace test{
void
fed_a_custom_finishing_functor()
{
using TestFactory = factory::MuttiFac<int(int), theID, factory::Build<long>::Wrapper>;
TestFactory theFact;
// Setup(1): each "production line" does a distinct calculation
theFact.defineProduction (ONE, [](int par) { return par; });
theFact.defineProduction (TWO, [](int par) { return 2 * par; });
theFact.defineProduction (THR, [](int par) { return par*par; });
theFact.defineProduction (FOU, [](int par) { return 1 << par;});
// Setup(2): and a common "wrapper functor" finishes
// the output of the chosen "production line"
theFact.defineFinalWrapper([](int raw) { return raw + 1; });
CHECK (long(1 + 1) == theFact(ONE, 1));
CHECK (long(1 + 2) == theFact(ONE, 2));
CHECK (long(1 + 3) == theFact(ONE, 3));
CHECK (long(1 + 2) == theFact(TWO, 1));
CHECK (long(1 + 4) == theFact(TWO, 2));
CHECK (long(1 + 6) == theFact(TWO, 3));
CHECK (long(1 + 1) == theFact(THR, 1));
CHECK (long(1 + 4) == theFact(THR, 2));
CHECK (long(1 + 9) == theFact(THR, 3));
CHECK (long(1 + 2) == theFact(FOU, 1));
CHECK (long(1 + 4) == theFact(FOU, 2));
CHECK (long(1 + 8) == theFact(FOU, 3));
}
};