Boost logo

Boost :

From: William Kempf (sirwillard_at_[hidden])
Date: 2000-11-17 18:59:10


--- In boost_at_[hidden], Douglas Gregor <gregod_at_r...> wrote:
> On Fri, 17 Nov 2000 21:41:45 -0000
> "William Kempf" <sirwillard_at_m...> wrote:
>
>
> > > I believe that we need partial specialization in any case. Even
if
> > we use Callback0, Callback1, etc. classes, we still (might) need
a
> > void (partial) specialization. e.g.,
> > >
> > > template<typename Arg1, typename Arg2>
> > > struct Callback2<void, Arg1, Arg2> { ... };
> > >
> > > I haven't toyed with the idea (since I tend to ignore VC++ as
much
> > as I'm allowed), but we may be able to come up with an
implementation
> > which correctly omits the "return" when the return type is void
> > without using partial specialization.
> >
> > This particular issue has a VC++ work around known to work, even
if
> > the resulting code is hard to read ;). The multiple arguments
are
> > MUCH harder to work around.
>
> I don't have the capability to test on VC++, but if the primary
Callback
> template were to have N+1 operator() overloads (corresponding to
having
> 0..N arguments), would VC++ still die? Only one of the operator()
will
> be instantiated, so possibly we can pull some casting tricks to
make the
> other operator() overloads appear valid to the compiler.

No, it wouldn't die. But you're wrong about only one function being
instantiated. The number instantiated is totally dependent on how
the programmer uses the class. You may be able to get it down so
that only one can legally be instantiated, which may be good enough.
I'll have to work on an implementation.

Again, I think it's a good idea, I'm just worried about the work
involved. After having tried to get tuples working on VC++ I'm very
leary about finding work arounds for cases that logically use partial
template specialization. Even the easy work arounds have a tendency
to become unwieldy if not simply impossible to implement.

> IMHO, this is mostly a stylistic issue, unless someone finds a
compelling
> technical reason to support or reject either approach.

Yes, it's a stylistic issue, but one based on usability. I
definately think the single class approach is easier to comprehend
and use than the multiple classes for varying sized argument lists
approach. If we can implement it on VC++ I think I'm in favor of it.
  
> > which may have different criteria for the bool conversion. Here's
a
> > strange example that I don't believe can be covered with your
version:
> > >
> > > class KeyboardInputEvent : public EventBase<char>
> > > {
> > > virtual operator bool() { return is_key_pressed(); }
> > > virtual char operator()() { return get_key_pressed(); }
> > >
> > > // implement other virtual methods as needed
> > > };
> > >
> > > Event<char> getUserInput = KeyboardInputEvent(...);
> > >
> > > if (getUserInput) {
> > > char input = getUserInput();
> > > // Act on the user's input...
> > > }
> > >
> > > I do believe this example has merit, and that existance of a
> > functor is not the only criteria by which the bool conversion
should
> > be performed. Perhaps I can conjure a more convincing example.
> >
> > Please do. This particular example at first seems compelling.
> > However, you're looking at this as an "event" while I'm looking
at it
> > as a "callback". Though related they are different concepts.
> > Realizing that, if the above functionality is not common it may
make
> > more sense to have both concept types, building the event type
out of
> > the callback type.
>
> The obvious question of "which does Boost need?" comes to mind. It
seems
> that the only difference between an event and a callback that we
have
> listed is that an event can turn itself off, which is to some
extent a
> minor difference, since a callback is just an event that is always
on.
> Are there any other differences that should be discussed?

The ability for external criteria to turn off an event would make it
VERY problematic to use for thread creation, which bolstered me to
push for discussion here. No, what I need is a callback, not an
event. The nice thing is, if we have a callback that's well defined
and implemented, it can be the basis for many other related types,
such as events (or Singals/Slots, which are synonymous with your
MultiEvent).
 
> > I wasn't really advocating the removal of the creation function,
only
> > questioning the need for multiple class types for functions,
member
> > functions and functors.
>
> The Functor implementation class is the only essential class. The
> otherwise were included because I believed them to enhance type and
> runtime safety (e.g., a NULL function pointer will never be called).
> These concerns can be addressed in other places, but I think it
would
> be a mistake to allow a user to pass a NULL function pointer and
then
> have the callback code dereference it.

This kind of safety should really be addressed by the code that
implements the functors.
 
> > > The usefulness of the "event" function is that, from a free
> > function pointer or a member function pointer passed to event, we
> > already know the argument types, so we can construct the
appropriate
> > (Member)FunctionEvent object.
> > >
> > > The assignment operation could, of course, be templated for any
> > functor, so we just write:
> > > myEvent = put_a_functor_here;
> > >
> > > In this case I worry about type safety, though there a probably
a
> > type-safe solution to this that I'm not seeing.
> >
> > Might be simplest to just include a reassign() method instead of
an
> > operator=(). This would be as type safe as the templated
constructor
> > in the original implemenation.
>
> I think operator=() is most natural.

Not when applied to Lambda expressions. Does the following really
make sense?

callback<void, int> cb;
cb = cout << free1 << endl;

In contrast, reassign is understandable and intuitive for either.

> As for the original templated
> constructor, I dislike where an error will occur if an incorrect
> functor type is given to the callback, which will be way down in the
> detail::callback0_impl::operator() function. Using the more rigid
> approach with the three implementation classes, this error will be
> picked up when an assignment is attempted.

This can be handled with Concept Checking :). No, I don't have code
to do this yet, but I don't see any other way to handle arbitrary
functors.


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