|
Boost : |
From: Marco Costalba (mcostalba_at_[hidden])
Date: 2007-09-18 08:15:11
On 9/17/07, Tobias Schwinger <tschwinger_at_[hidden]> wrote:
>
> Try plugging your function object into boost::unfused_generic.
>
>
Hi Tobias,
I have found a solution this way (and it works):
These are the overloads according to the number of arguments (I just
show 2 of them)
template<typename T1>
static Base* object(detail::KeyRef nm, T1 a1)
{
typedef boost::fusion::vector<T1> Args;
typedef typename detail::tie_sequence<Args>::type Values;
Values v(boost::fusion::vector_tie(a1));
return detail::Dispatcher<Base>::instance().template doObject<Values,
Args>(nm, v);
}
template<typename T1, typename T2>
static Base* object(detail::KeyRef nm, T1 a1, T2 a2)
{
typedef boost::fusion::vector<T1, T2> Args;
typedef typename detail::tie_sequence<Args>::type Values;
Values v(boost::fusion::vector_tie(a1, a2));
return detail::Dispatcher<Base>::instance().template doObject<Values,
Args>(nm, v);
}
Then this is the _only_ inner common functions that is called by all
the overloads:
template<typename Values, typename Args>
Base* doObject(KeyRef nm, Values& v) const
{
Range r;
if (!find_range<Args>(nm, r))
return NULL; /* no function with the same number of arguments */
const SignatureClass<Base, Args>* p = find<Args>(r);
if (p)
return (*p)(v); /* perfect match found */
return NULL;
}
And finally this is the functor wrapper from which the operator() is invoked:
/* 'FactoryClass' is subclassed from 'SignatureClass' and stores
* the functor object used to create the requested object,
* will be called due to dynamic polymorphism
*/
template<typename Base, typename Args, typename Functor>
struct FactoryClass: public SignatureClass<Base, Args>
{
typedef typename tie_sequence<Args>::type Values;
typedef typename Functor::result_type result_type;
FactoryClass(const Functor& fn) : _functor(fn) {}
virtual result_type operator()(Values& v) const
{
return boost::fusion::invoke_function_object(_functor, v);
}
Functor _functor;
};
Where the base SignatureClass is:
/* 'SignatureClass' is subclassed from StorableType and identifies
* an unique argument list type (without return value). Used by
* runtime argument checking
*/
template<typename Base, typename Args>
struct SignatureClass : public StorableClass
{
// at runtime values passed to operator() are stored
// in a tied vector, so set the signature accordingly
typedef typename tie_sequence<Args>::type Values;
virtual Base* operator()(Values&) const = 0;
};
That is derived from the argument agnostic, storable in a map, base class:
/* 'StorableType' is the common base class to store pointers
* to different type of creators, dynamic_cast<> at runtime
* will be used to check the (hidden) derived type
*/
struct StorableClass
{
virtual ~StorableClass() {}
};
BTW I studied your factory and also your suggestion to use a map as a
dispatcher to create a complete object factory from your one.
The problem is that the classes must be registered at instantation
time. IOW your factory (+ a map framework to act as dispatcher) does
not seem to support the concept of adding new classes at runtime,
everything must be already known at instantation/definition time.
Please correct me if I'm wrong.
Thanks
Marco
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk