"Interface" as semantics with boost :: bind

I wanted to have something like the semantics of a Java interface with C ++. First, I used boost::signal to call back explicitly registered member functions for this event. It worked very well.

But then I decided that some pools of callback functions are connected, and it makes sense to abstract and register them for all callbacks associated with the instance. But I found out that the specific nature of boost::bind and / or the adoption of this seemed to make that break. Or perhaps the fact that the declaration of the add_listener(X &x) method changed the code generated by boost::bind .

I have a very rough understanding of why the problem occurred, and I think that it probably works correctly in accordance with its design. I'm curious: what should I have done instead? Of course, there is the right way to do this.

Here is a sample 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; } 

Well, I did not describe the problem completely. The name is misleading.

Oh man. Bring it down. I obviously did not describe the problem very well, and I think it ultimately comes down to a syntax error. :(

+2
source share
2 answers

boost::bind takes its parameters by value and copies them. It means

 f = boost::bind<void>(boost::mem_fn(&X::go), x); 

will give a copy of x , which will cut off a piece of Y (if it was really Y for a start). For virtual dispatching to work, you need to pass a pointer to boost::bind :

 f = boost::bind(&X::go, &x); 

(Note that you really don't need to mem_fn or explicitly write <void> , since boost::bind and the argument output will take care of them for you.)

+3
source

Java interfaces do not exist in C ++. Closest you can get clean abstract base classes. This is usually close enough.

The rest of your question is not about interfaces. Java uses the Observer pattern to connect to events and send. The interface part is only slightly connected, because observers must obey certain interfaces (of course, since otherwise you would not have a clue what to call).

Using boost :: bind to create functors is actually an abstraction outside of the interfaces and thus is a more general solution. The observer pattern and functors are combined into idioms / patterns of signals / slots implemented in various libraries, such as boost :: signals, boost :: signals2 and gtk ++. The Qt version differs differently in mechanics, but is similar in concept.

So what does it mean to help you understand what, why, and where? I would suggest starting with a search for what the Observer pattern is, and trying to write a few implementations.

0
source

All Articles