Boost logo

Boost :

From: Douglas Gregor (gregod_at_[hidden])
Date: 2001-05-08 08:18:55


On Monday 07 May 2001 08:45 pm, you wrote:
> 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==.

<Doug looks at the mess that is boost::function, shakes his head and grumbles
about virtual function overhead>

> 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

Here's what I've been considering:

function is:
        - Assignment from any target function object
        - Clearing out the value (assignment from nil)
        - Execution of that target function object
        - A check to see if it is empty

callback extends function:
        - Equality test

signal is a distinct function-like concept:
        - support for multiple slots
        - notification to slot when it dies
        - method of combining multiple return values

slot extends function:
        - knowledge of which signals it points to
        - notification to those signals when it dies
        - picks up notification of signal death

        Doug


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