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:
parent
932d49fd95
commit
591e6d9775
2 changed files with 83 additions and 10 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue