
Boost : 
From: Jesse Jones (jesjones_at_[hidden])
Date: 20010507 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 metafunction 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 metafunction 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