Boost logo

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