I wanted to be able to have something like Java's interface semantics with C++. At first, I had used boost::signal
to callback explicitly registered member functions for a given event. This worked really well.
But then I decided that some pools of function callbacks were related and it made sense to abstract them and register for all of an instance's related callbacks at once. But what I learned was that the specific nature of boost::bind
and/or taking the value of this
seemed to make that break. Or perhaps it was just the fact that the add_listener(X &x)
method declaration changed the code that boost::bind
generated.
I have a very rough understanding why the problem occurred and I think it's probably functioning correctly as per its design. I am curious: what should I have done instead? Surely there's a Right Way to do it.
Here's some example code:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
using namespace std;
struct X;
struct Callback
{
virtual void add_listener(X &x) = 0;
};
struct X
{
X() {}
X(Callback &c) { c.add_listener(*this); }
virtual void go() { cout << "\t'" << __PRETTY_FUNCTION__ << "'" << endl; }
};
struct CallbackReal : public Callback
{
virtual void add_listener(X &x)
{
f = boost::bind<void>(boost::mem_fn(&X::go), x);
}
void go() { f(); }
boost::function<void (void)> f;
};
struct Y : public X
{
Y() {}
Y(Callback &c) { c.add_listener(*this); }
virtual void go() { cout << "\t'" << __PRETTY_FUNCTION__ << "'" << endl; }
};
int main(void)
{
CallbackReal c_x;
CallbackReal c_y;
X x(c_x);
Y y(c_y);
cout << "Should be 'X'" << endl;
boost::bind<void>(boost::mem_fn(&X::go), x)();
cout << "Should be 'Y'" << endl;
boost::bind<void>(boost::mem_fn(&X::go), y)();
cout << "------------------" << endl;
cout << "Should be 'X'" << endl;
c_x.go();
cout << "I wish it were 'Y'" << endl;
c_y.go();
return 0;
}
Okay, I did not describe the problem completely. The title is misleading.
Oh, man. Downvote this one. I obviously haven't described the problem well and I think this ultimately boils down to mostly a syntactical error. :(