MultiFact: how I learned to love the Bomb
C++11 is just incredibly cool. It is so easy to support a flexible yet specific set of arguments
This commit is contained in:
parent
372edbfc85
commit
932d49fd95
2 changed files with 85 additions and 6 deletions
|
|
@ -178,7 +178,28 @@ namespace lib {
|
|||
using WrappedProduct = typename WrapFunctor::ResultType;
|
||||
|
||||
typedef BareProduct SIG_Fab(void);
|
||||
|
||||
enum{ ARGUMENT_CNT = 0 };
|
||||
};
|
||||
/**
|
||||
* @internal specialisation to deal with the generic case:
|
||||
* using an arbitrary fabrication function with multiple arguments
|
||||
*/
|
||||
template< typename RET
|
||||
, typename... ARGS
|
||||
, template<class> class Wrapper
|
||||
>
|
||||
struct FabConfig<RET(ARGS...), Wrapper>
|
||||
{
|
||||
using WrapFunctor = Wrapper<RET>;
|
||||
using BareProduct = typename WrapFunctor::BareType;
|
||||
using WrappedProduct = typename WrapFunctor::ResultType;
|
||||
|
||||
typedef BareProduct SIG_Fab(ARGS...);
|
||||
|
||||
enum{ ARGUMENT_CNT = sizeof...(ARGS)};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -219,17 +240,33 @@ namespace lib {
|
|||
public:
|
||||
using Product = typename _Conf::WrappedProduct;
|
||||
|
||||
/**
|
||||
* Core operation of the factory:
|
||||
* Select a production line and invoke the fabrication function.
|
||||
* @param id select the actual pre installed fabrication function to use
|
||||
* @param args additional arguments to pass to the fabrication.
|
||||
* @note the template parameter #SIG defines the raw or nominal signature
|
||||
* of the fabrication, and especially the number of arguments
|
||||
* @return the created product, after passing through the #Wrapper functor
|
||||
*/
|
||||
template<typename... ARGS>
|
||||
Product
|
||||
operator() (ID const& id)
|
||||
operator() (ID const& id, ARGS&& ...args)
|
||||
{
|
||||
static_assert (sizeof...(ARGS) == _Conf::ARGUMENT_CNT,
|
||||
"MultiFac instance invoked with the wrong number "
|
||||
"of fabrication arguments. See template parameter SIG");
|
||||
|
||||
Creator& creator = selectProducer (id);
|
||||
return this->wrap (creator);
|
||||
return this->wrap (creator, std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
/** more legible alias for the function operator */
|
||||
template<typename... ARGS>
|
||||
Product
|
||||
invokeFactory (ID const& id) ///< alias for the function operator
|
||||
invokeFactory (ID const& id, ARGS&& ...args)
|
||||
{
|
||||
return this->operator() (id);
|
||||
return this->operator() (id, std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -74,13 +74,17 @@ namespace test{
|
|||
class Implementation
|
||||
: public Interface
|
||||
{
|
||||
string instanceID_;
|
||||
|
||||
operator string()
|
||||
{
|
||||
return "Impl-"+lexical_cast<string> (ii);
|
||||
return instanceID_ + lexical_cast<string> (ii);
|
||||
}
|
||||
|
||||
public:
|
||||
// static theID getTypeID() { return ii; }
|
||||
Implementation(string id = "Impl-")
|
||||
: instanceID_(id)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -239,6 +243,44 @@ namespace test{
|
|||
void
|
||||
pass_additional_arguments()
|
||||
{
|
||||
using TestFactory = factory::MuttiFac<Interface*(string), theID>;
|
||||
|
||||
TestFactory theFact;
|
||||
|
||||
// the first "production line" is wired to a free function
|
||||
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); });
|
||||
theFact.defineProduction (FOU, [](string id) { return new Implementation<FOU>("Z"+id);});
|
||||
|
||||
Interface *p1 = theFact(ONE, "irrelevant"),
|
||||
*p2 = theFact(TWO, "ignored"),
|
||||
*p3 = theFact(THR, "idiocy"),
|
||||
*p4 = theFact(FOU, "omg"),
|
||||
*p5 = theFact(FOU, "z");
|
||||
|
||||
// does not compile...
|
||||
// theFact(ONE);
|
||||
// theFact(ONE, "foo", bar);
|
||||
|
||||
CHECK ("Impl-1" == string(*p1));
|
||||
CHECK ("X2" == string(*p2));
|
||||
CHECK ("idiocy3"== string(*p3));
|
||||
CHECK ("Zomg4" == string(*p4));
|
||||
CHECK ("Zz4" == string(*p5));
|
||||
|
||||
CHECK (!isSameObject(*p4, *p5));
|
||||
CHECK (INSTANCEOF(Implementation<ONE>, p1));
|
||||
CHECK (INSTANCEOF(Implementation<TWO>, p2));
|
||||
CHECK (INSTANCEOF(Implementation<THR>, p3));
|
||||
CHECK (INSTANCEOF(Implementation<FOU>, p4));
|
||||
CHECK (INSTANCEOF(Implementation<FOU>, p5));
|
||||
|
||||
delete p1;
|
||||
delete p2;
|
||||
delete p3;
|
||||
delete p4;
|
||||
delete p5;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue