|
Boost : |
From: Jody Hagins (jody-boost-011304_at_[hidden])
Date: 2004-02-17 22:50:50
On Tue, 17 Feb 2004 18:45:19 -0500
Douglas Gregor <gregod_at_[hidden]> wrote:
> Well, we could throw bad_function_call, perhaps, or pick/create some
> other exception (I'm at a loss for exception names for this).
Either way... if you create a new one, maybe something like
no_slots_connected.
> Well, you can always write a different combiner that does this.
Right, but then that is a fair amount of work to duplicate the code for
the current one, to avoid the assertion. Not much way to actually use
the existing code the way it is.
> No, it isn't pretty; perhaps the exception is the right way to go,
> depending on your application.
Currently, I am doing the check for empty. Actually, I wanted to
discuss my application with you, because it is actually an extension of
the signal/slot mechanism.
Consider the case where you want to signal events with multiple types.
Since a slot and signal have to match signatures explicitly, you are
limited in how you can direct the signals. Specifically, you must know
exactly which signal object can "signal" certain events.
Consider a slot that has the following interface:
struct some_slot
{
void operator()(some_class const & sc)
{
}
};
This slot must be connected with a signal of the type
boost::signal<void (some_class const&)>
which means that that the connection logic must know which signal object
meets that criteria. Suppose you have many different signatures (or
think of it is events) that you want to dispatch (i.e., signal).
What I want is the ability to have a single signal that can dispatch
multiple signatures (but I do not want to give up any type safety). For
example, what I have now is very much like:
boost:multisignal sig;
sig();
sig(some_class());
sig(yet_one_more_class());
The underpinning is based upon typesafe access (demux based on the type)
to the right bost::signal instance, and then forwarding the signal
dispatching to that signal, and I have a protoyype that allows this as
well:
sig(another_class(), and_another_class());
This provides power and flexibility to many of our applications, and
allows us to create specific event objects, and then dispatch them via a
single multisignal object, not really caring about the type of the
object that we are dispatching, since the multisignal will correctly
(and safely) take care of that redirection.
A typical "slot" might have multiple handler functions...
struct some_slot
{
void operator()();
void operator()(some_class const &);
void operator()(another_class const &, and_another_class const &);
};
Currently, the connection is a bit tricky, and has to be done explicitly
(or wrapped with clever type lists)...
sig.connect<some_class>(a_slot);
so that the multisignal knows that a_slot is interested in signals that
have some_class as the signature. I have not yet found a way to
automatically deduce all the "operator()" function signatures. If I
could, then connection to all the proper underlying signals would be
much nicer as well.
If you are interested, I'd be willing to carry on a discussion offline
(unless there are enough sig/slot users interested in this). I will
admit that nothing is new under the sun, so this may have already come
up and been discounted. I have been using a very similar technique for
years, and ported the ideas on top of sig/slot when I first started
playing with boost, since it decouples the code from any other internal
libraries.
Some of the more advanced features are not yet ported to boost::signals,
because they are implemented using the loki typelist stuff, and I have
as of yet played with whatever boost component would replace that stuff
(I imagine that would be mpl).
-- Jody Hagins The early bird who catches the worm works for someone who comes in late and owns the worm farm. -- Travis McGee
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk