Boost logo

Boost Users :

From: Darren Vincent Hart (dvhart_at_[hidden])
Date: 2003-05-30 09:56:30


I am building a widget set using the signals and slots library. I have
the need to be able create a functor (FA) that receives another (FB) as
an argument to its constructor. I will connect FA to the signal of a
widget, when FA is run it will perform a test and execute FB if
appropriate. I want to be able to use the signal member of another
widget as FB, so I am trying to use bind to get that function object for
the signal. I am experiencing two problems:

1) When the member functor (FB) is bound to the signal of another
widget, the slots don't get called. (No error results, but the connected
slot doesn't print anything so I am assuming it isn't being executed).

2) I can't get it to compile when the signal has a <bool ()> signature,
I can only get it to compile with a <void ()> signature. I am trying to
assign the result of bind to a boost::function<bool ()> but I get an
error saying it can't make the conversion, what type should I be using
if not boost::function (note that it works if the signal is void())?

The following is a commented test_case demonstrating the problem. Any
assistance in binding to signals and compiling those with a bool()
signature would be greatly appreciated.

Thanks in advance,

Darren Hart

compile with:
g++ test.cpp -o test -lboost_signals

// test.cpp ----------------------------------------------------------
#include <iostream>
#include <boost/signal.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

using namespace std;

struct widget
{
        boost::signal<bool ()> sig;
        boost::signal<bool (char)> keypress;
        bool test()
        {
                cout << "widget::test() - sig empty: " << (sig.empty() ? "true" :
"false") << endl;
                sig();
                return true;
        }
};

template <typename T>
struct handler
{
        boost::function<T ()> slot_;
        handler(boost::function<T ()> slot) : slot_(slot) { }
        bool operator()(char letter)
        {
                cout << "handler::operator() - received a " << letter << endl;
                if (letter == 'A')
                {
                        cout << "\texecuting slot\n\t";
                        slot_();
                        cout << endl;
                }
                return true;
        }
};

struct no_op
{
        bool operator()() { cout << "no_op::operator() - doing nothing" <<
endl; return true; }
        bool test() { cout << "no_op::test()" << endl; return true; }
};

int main()
{
        // instantiate two widgets
        widget widget_a;
        widget widget_b;
        
        /* The goal is to connect the hanlder to widget_b which will then call
         * widget_a's sig signal. The problem is that even though widget_a's
         * test says that sig() isn't empty, it doesn't execute when bound
         * directly in handler_b. It does however work when called as part
         * of the test() member function as in handler_c. We must get
         * handler_b to work in order to do this in libstk! We can't compile
         * at all if the signal returns a bool.
         */
        
        // instanstiate the function objects
        no_op no_op_;
        // bind to a no_op member, successul
        handler<bool> handler_a( boost::bind(&no_op::test, &no_op_) );
        
        // bind to a widget signal handler, BROKEN
        //handler<bool> handler_b( boost::bind<bool>(&widget::sig, &widget_a)
); // <-- Broken
        
        // bind to a widget member, successul
        handler<bool> handler_c( boost::bind(&widget::test, &widget_a) );
        
        
        // connect the function objects to the widgets
        widget_a.sig.connect(no_op_);
        widget_b.keypress.connect(0, handler_a);
        //widget_b.keypress.connect(1, handler_b); // fix handler_b above, then
uncomment this
        widget_b.keypress.connect(2, handler_c);
        
        cout << "attempting to bind to widget_a's sig signal" << endl;
        // store the function object returned by binding a widget signal,
BROKEN
        //boost::function<bool ()> fp = boost::bind(&widget::sig, &widget_a);
// <-- BROKEN
        
        // executre the functor returned by binding a widget signal, BROKEN
        // (builds, but doesn't really call widget_a.sig())
        boost::bind(&widget::sig, &widget_a)(); // <-- Test if binding works
at all, it doesn't
        
        // signal the keypress signals, they will test the character and
execute their
        // slots if it equals 'A'
        cout << "signalling widget_b.keypress('B')" << endl;
        widget_b.keypress('B'); // call the handler 3 times, but never execute
its slot
        cout << "***\nThis correctly executed the three handlers which, also
correctly,"
                   << " do not execute their slots\n***" << endl;
        cout << "signalling widget_b.keypress('A')" << endl;
        widget_b.keypress('A'); // call the handler 3 times, executing the slot
        cout << "***\nThis executes the three handlers, but handler_b calls
slot_() "
                   << "and widget_a's signal does not execute the slot it has, which
the "
                         << "test() in handler_c successfully executes.\n***" << endl;
        
        return 0;
}
// --------------------------------------------------------------------


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net