copying sigc::signals



So, I made a rather surprising (to me) discovery the other day.  When
you copy a signal, any slots that you connect to the copied signal will
also be triggered when you emit the original signal.  Perhaps this is
better explained by the following code:

=====================
#include <iostream>
#include <sigc++/signal.h>

void foo ()
{
    std::cout << "FOO" << std::endl;
}

void bar ()
{
    std::cout << "BAR" << std::endl;
}

int main (int argc, char** argv)
{
    sigc::signal<void> sig1;
    sig1.connect (sigc::ptr_fun (foo));
    sigc::signal<void> sig2 (sig1);
    sig2.connect (sigc::ptr_fun (bar));
    sig1.emit ();

    return 0;
}
=====================

I had expected that running this program would result in only "FOO"
being printed to the terminal (since the bar slot was not connected to
the original signal object), but in fact, both "FOO" and "BAR" are
printed to the terminal.  Looking at the implementation, it seems that
this is intentional, but it seems like a bit of a strange design
decision to me.  Can somebody explain it to me?

In practical terms, this means that any classes containing sigc::signals
that don't want their signals to be triggered when their copies are
emitted *must* define a custom assignment operator and copy constructor
that intentionally doesn't copy these signal members.  For instance, the
following does not work how I had expected:

=============
class Foo
{
public:
    Foo () : x (0) {}
    set_x (int new_val) { x = new_val; signal_changed ().emit ();}
    sigc::signal<void>& signal_changed ();
private:
    int x;
    sigc::signal<void> m_signal_changed;
};

// usage

Foo f;
Foo g = f;
g.set_x (3);
===============

Even though only one of those objects actually changed, the slots
connected to the signals of both objects will be triggered by the call
to set_x().

I don't know if everybody else already knew this or not, but since I
just spent a little while debugging this issue and was a bit surprised
by what I found, I thought I'd share.

jonner



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