Re: [sigc] Signals & Slots



Murray Cumming wrote:
> I doubt that Boost Signals and libsigc++ 2 are significantly
> different.
> 
> A comparison should probably start by looking at the application code
> needed to
> 1. Create a signal
> 2. Connect a slot (callback function) to a signal.
>   2.2 For a member method.
>   2.3 For a non-member or static function.
> 3. Disconnect a slot.
> 4. Bind an extra parameter, so that e.g. a slot with 4 parameters can
> be
> used with a signal with 3 parameters. I don't personally find the more
> complex adaptors interesting.


Here are two working examples.  The libsigc version is based on what
Murray wrote, and the Boost.Signal version was written by me, after
reading the docs for Boost.Signal.

Under GCC 3.3.5 and 3.4.2, the Boost.Signal version compiles 3x and 4.3x
slower than the libsigc++ version for each compiler.  The file sizes for
the object code are 2x and 3.2x larger.

The preprocessed source for the Boost.Signal version is 1.5 MB; the
libsigc version preprocesses to 568 KB (800 KB if you just #include
<sigc++/sigc++.h>).

The source code sizes for the two files are essentially the same.

Aesthetically, I prefer the convenience of sigc::mem_fun over
boost::bind for the simple case, since bind requires placeholders for
every argument that isn't being bound  (the phrase, "Using a cannon to
swat a fly comes to mind).  I prefer boost::bind over sigc::mem_fun for
the case of actually binding arguments to the functor, since it appears
clearer to me at a glance.

What would it take to adapt libsigc++ to accept boost::bind function
objects as callbacks?

Thanks,
-Jonathan
#include <boost/signal.hpp>
#include <boost/bind.hpp>

class A {};
class B {};
class C {};

class SomeClass : public boost::signals::trackable
// Note that objects do not need to be trackable.  Non-trackable signals will
// be silently allowed.  Attempting to call one after it is gone may just 
// crash.
{
 public:
    int on_signal( A, B);
    static int on_signal_static( A, B);
    int on_signal_extra( A, B, int);
};


int main(void)
{
    //Create a signal whose handler would look like this:
    //int SomeClass::on_signal(A a, B b);
    boost::signal<int (A, B)> signal_example;
    
    //If This is an instance of SomeClass.
    SomeClass This;
    // Note that the bind() expression gets longer for more arguments, since
    // each unbound arg requires a placeholder.
    signal_example.connect( boost::bind( &SomeClass::on_signal, This, _1, _2));
    signal_example.connect( &SomeClass::on_signal_static);

    //If I save the connection, like so:
    boost::signals::connection con = signal_example.connect( 
        boost::bind( &SomeClass::on_signal, This, _1, _2) );

    //then I can do:
    con.disconnect();

    //If we have a signal handler that look like this:
    //int SomeClass::on_signal(A a, B b, int c);
    //but the signal was declared as
    //sigc::signal<int, a, b> signal_example;
    //then we can do:
    signal_example.connect( 
        boost::bind( &SomeClass::on_signal_extra, This, _1, _2, 1));
}
#include <sigc++/bind.h>
#include <sigc++/signal.h>
#include <sigc++/slot.h>
#include <sigc++/trackable.h>
#include <sigc++/connection.h>

class A {};
class B {};
class C {};

class SomeClass
// Note that objects do not need to be trackable.  Non-trackable signals will
// be silently allowed.
{
 public:
    int on_signal( A, B);
    static int on_signal_static( A, B);
    int on_signal_extra( A, B, int);
};

int main(void)
{

    //Create a signal whose handler would look like this:
    //int SomeClass::on_signal(A a, B b);
    sigc::signal<int, A, B> signal_example;

    SomeClass This;
    //If this is an instance of SomeClass.
    signal_example.connect( sigc::mem_fun(This, &SomeClass::on_signal) );
    signal_example.connect( sigc::ptr_fun(&SomeClass::on_signal_static) );

    //If I save the connection, like so:
    sigc::connection con = signal_example.connect( sigc::mem_fun(This,
        &SomeClass::on_signal) );

    //then I can do:
    con.disconnect();
    //If we have a signal handler that look like this:
    //int SomeClass::on_signal(A a, B b, int c);
    //but the signal was declared as
    //sigc::signal<int, a, b> signal_example;
    //then we can do:
    signal_example.connect( sigc::bind( sigc::mem_fun(This,
        &SomeClass::on_signal_extra), 1 /* the value for c */ ));
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]