Boost logo

Boost :

From: Douglas Gregor (gregod_at_[hidden])
Date: 2000-11-17 14:24:10

On Thu, 16 Nov 2000 22:35:29 -0000
"William Kempf" <sirwillard_at_[hidden]> wrote:

> So... before we discuss the thread specific stuff I'd like to first
> address callbacks. I've read all the articles on the subject that I
> can get my hands on and it seems they all take different approaches
> (the Kubrick article covers several of them), each with varying pros
> and cons. I'd like to describe what requirements I think our version
> of callbacks need to take just to make sure everyone agrees with my
> opinions before we attempt to create an actual implementation.
> 1. Need to allow traditional functor types as the callback so that
> function pointers, standard functors, hand coded functors and Lambda
> Library style functors can all be used with relative ease.
> 2. The callback type(s) should be templatized on the return type and
> argument types, but not on the functor type to simplify useage.
> 3. Copying a callback should be quick, on par with copying a
> function pointer. This is not gauranteed with functors but becomes
> somewhat important with callbacks that may be stored, copied and
> passed around frequently in some cases.
> 4. A callback should itself be a functor.
> 5. Compiler type coercion should be possible to apply to the functor
> that the callback wraps for all parameters and the return value.
> 6. Executing a callback should be nearly as efficient as executing
> the contained functor.

I've written a small library ( which already fulfills all requirements except for #3 (due to memory allocations in the copy). I'll Boostify and submit it if there is sufficient interest. In the library, I referred to callback as "events", so consider the terms interchangeable for now and I would happily change the terminology during Boostification. Now to a library usage summary:

Usage of events in the library is simple. An event object is declared based on its return type and argument types:
        Event<float, int, int> myEvent;
The target of the myEvent can be changed via assignment and can be any functor, free function, or member function:
        float myDivide(int a, int b) { return (float)a / (float)b; }
        myEvent = event(myDivide);
And Event objects are functors:
        float eventResult = myEvent(5, 3);

Event objects are also convertible to bool so we can check if there is any target of an event:
        if (myEvent)
          eventResult = myEvent(5, 4);
Attempting to invoke an event with no target causing an exception (unless the return type is void, in which case nothing is done).
Attached is a longer example of using events.

The implementation of "Event" is such that it supports up to some arbitrary number of arguments, which is defined when the code is generated (Perl scripts generate each of the event classes). The primary template template parameter list is defined as:
  typename Return,
  typename Arg1 = Unused,
  typename Arg2 = Unused,
  typename ArgN = Unused
{ /* ... */ }; that Unused classes will pad any unspecified arguments, and partial specializations are provided for any number of arguments up to "N". Internally, each event type (free function, member function, functor) derives from an abstract class EventBase and Event stores an EventBase pointer.

        Doug Gregor

Boost list run by bdawes at, gregod at, cpdaniel at, john at