
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; } // --------------------------------------------------------------------