Boost logo

Boost :

From: Douglas Gregor (gregod_at_[hidden])
Date: 2001-05-07 02:16:04


On Sunday 06 May 2001 03:57, you wrote:
> >Taking the address of a function instantiates
> >it, and instantiation of equal() requires that operator== be available in
> >FunctionObj. The concept check library relies on this behavior (taking the
> >address of a function requires instantiation) to check its constraints.
>
> Right.
>
> >3) There's more to this as well - the two function0 objects don't
> > necessarily have targets of the same type, so a manager check would be
> > necessary. Additionally, we could have:
> >
> >int my_fun(int);
> >function<void, int> f1 = &my_fun;
> >function<int, int> f2 = &my_fun;
> >
> >And we'd probably want to have (my_fun == my_fun), which makes things even
> >nastier.
>
> Well the function objects are distinct types so I don't think anyone
> will complain if you can't compare the two.
>
> >The only way I can see to handle operator== without requiring it of all
> >function objects is to do it dynamically by keeping track of the
> >std::type_info associated with the contained function object/pointer and
> >using it for dynamic dispatch to an operator==; this would require a bit
> > of user maintenance, though.
>
> Yeah, I see now why you thought it was a sticky problem. I think it's
> time to decide on what we're trying to achieve here. It seems to me
> that that are two problem domains boost::function is trying to
> address. The first, let's call it the callback domain, is used for
> things like button click handlers, timer callbacks, and other sorts
> of notifications. It will usually only be applied to member function
> pointers and occasionally free functions (and functors that contain
> one of these and one or more bound arguments). The second, let's call
> it the functor domain, deals more with generic programming using
> things like std::transform. In this domain function objects are used
> more heavily.
>
> It'd be great if we could address these two domains with a single
> class, but it seems like we're going to have to make a trade-off
> somewhere. Personally I think that callbacks are used a lot more
> often than functors. And being able to compare two callbacks *is*
> useful functionality. If this requires that clients have to define an
> operator== for function objects that would be unpleasant, but worth
> the ugliness from my POV.
>
> -- Jesse

I'm not entirely convinced that comparing two boost::function objects is
necessary for the callback domain. I don't currently deal with callbacks
much, but in my prior life as a GUI person I don't recall ever needing to
compare callbacks.

In the timer example you gave it is convenient to have function pointers, but
I'm not sure that's the "right way" to do things because it places extra
requirements on the caller that may be tough to handle: what if my timer
could point to one of several different callback targets? Then I have to keep
track of which one was assigned anyway - is this better than keeping track of
a "Timer" object (or a "TimerHandle" object) that would be used to remove the
timer? What if two timers end up pointing to the same type of function
object?

I'm almost wondering if there really is a fundamental difference between the
two domains or if the lack of tools to enable the use of the "functor" domain
in C++ is the cause of the difference. If the binder and lambda libraries
were generally available and understood, would we be so reliant on the
standard callback types, to functions and member functions? I'll admit a
large degree of bias here because I tend to use the "functor" domain quite
often in my own code.

I think that requiring operator== of every function object is too
restrictive: standard library function objects don't support it, and likely
neither will functors created by boost::bind or the lambda library, which
will create a big hassle for users.

        Doug


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