Boost logo

Boost :

From: Jesse Jones (jesjones_at_[hidden])
Date: 2001-05-07 19:45:39


I've been experimenting with adding support for comparisons to my
callback proposal from last year. The overall design is quite a bit
simpler than Gregor's code, but it has the same sort of problems if
you try to add operator==.

What I did was create two classes: boost::function which behaves more
or less like Gregor's class and boost::callback which is the same,
but adds operator==. The key difference between the two is that
callback passes true to the meta-function that generates the concrete
functor objects (I'd upload the code, but Yahoo groups is down):

template <typename RETURN_TYPE,
           typename ARG1 = details::unused_arg,
           typename ARG2 = details::unused_arg>
class callback {

public:
public:
     template <typename FUNCTOR>
     callback(FUNCTOR functor) :
        mFunctor(new typename details::
        generate_functor<FUNCTOR, RETURN_TYPE, ARG1, ARG2, true>::
        RET(functor)) {}

private:
     Functor* mFunctor;
};

The meta-function looks like this:

template <typename FUNCTOR,
           typename RETURN_TYPE,
           typename ARG1,
           typename ARG2,
           bool useCompare>
struct generate_functor {
    enum {selector = is_used<ARG1>::RET +
                     is_used<ARG2>::RET +
                     3*useCompare};

    typedef call_functor0<FUNCTOR, RETURN_TYPE,
                          DummyCompare<FUNCTOR> > f0;
    typedef call_functor1<FUNCTOR, RETURN_TYPE, ARG1,
                          DummyCompare<FUNCTOR> > f1;
    typedef call_functor2<FUNCTOR, RETURN_TYPE, ARG1, ARG2,
                          DummyCompare<FUNCTOR> > f2;

    typedef call_functor0<FUNCTOR, RETURN_TYPE,
                          CompareFunctor<FUNCTOR> > f0c;
    typedef call_functor1<FUNCTOR, RETURN_TYPE, ARG1,
                          CompareFunctor<FUNCTOR> > f1c;
    typedef call_functor2<FUNCTOR, RETURN_TYPE, ARG1, ARG2,
                          CompareFunctor<FUNCTOR> > f2c;

    typedef typename SWITCH<(selector),
       CASE<0, f0,
       CASE<1, f1,
       CASE<2, f2,

       CASE<3, f0c,
       CASE<4, f1c,
       CASE<5, f2c> > > > > > >::RET RET;
};

The functors used by callback and function have equal methods that
look like this:

template <typename FUNCTOR,
           typename RETURN_TYPE,
           typename COMPARE>
class call_functor0 : public base_call_functor0<RETURN_TYPE> {

public:
    virtual bool equal(const base_call_functor& rhs) const
    {
        const call_functor0* temp = dynamic_cast<const call_functor0*>(&rhs);
        return temp != nil && COMPARE::equal(mFunctor, temp->mFunctor);
    }

private:
    FUNCTOR mFunctor;
};

The comparisons are handled by the following structs:

template <typename FUNCTOR>
struct CompareFunctor {
     static bool equal(const FUNCTOR& lhs, const FUNCTOR& rhs)
{return lhs == rhs;}
};

template <typename FUNCTOR>
struct DummyCompare {
     static bool equal(const FUNCTOR&, const FUNCTOR&)
{assert(false); return false;}
};

This seems like a fairly good solution to me and I'm pretty sure
something like it could be made to work with Gregor's code...

   -- Jesse


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk