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 signature,
I can only get it to compile with a signature. I am trying to
assign the result of bind to a boost::function 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
#include
#include
using namespace std;
struct widget
{
boost::signal sig;
boost::signal keypress;
bool test()
{
cout << "widget::test() - sig empty: " << (sig.empty() ? "true" :
"false") << endl;
sig();
return true;
}
};
template <typename T>
struct handler
{
boost::function slot_;
handler(boost::function 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 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;
}
// --------------------------------------------------------------------