Encapsulating boost::signal and boost::bind code in class method

I am trying to encapsulate the binding and connection of a boost signal (which requires the method to call and the instance the method belongs to) within a class method. So ideally I'd like to say something like,

1
2
3
4
5
6
7
8
9
10
11
// app.cpp
...
void App::init() {
    Button btn;
    btn.addListener(&App::onClick, this);
}

void App::onClick() {
    cout << "Button was clicked" << endl;
}
...


1
2
3
4
5
6
// button.cpp

void Button::addListener(callback, object) {  // <-- how is the callback and object defined here
    boost::signal<void()> signal;
    signal.connect(boost::bind(callback, object));
} 


I understand that you cannot pass a reference to the instance version of app.onClick to btn.addListener. That being said then, I'm not sure it is possible to encapsulate the boost code from outside of App. If it is possible though, how would the signature for Button::addListener() look?


1
2
3
4
5
6
template< typename Fn, typename Obj >
void Button::addListener( Fn callback, Obj& object ) // Or Obj*
{
    boost::signal<void()> signal;
    signal.connect(boost::bind( callback, object ) );
}


Better yet is to have addListener take a boost::function<> to start with.
Oh, excellent. I'm glad the general principle is possible, at least.

I'm going to check out the other idea of the boost::function next but I just need some clarification on where to put the template code. Putting the implementation of the method in the header file works great like so:

1
2
3
4
5
6
7
8
9
10
11
12
// button.h

class Button {
...
template<typename Fn, typename Obj>
void addListener(Fn callback, Obj &object) {
	boost::signals2::signal<void ()> signal;
	signal.connect(boost::bind(callback, object));
	signal(); // executes the callback
}
...
};


but what if the implementation was going to be in the button.cpp file? Both the header and implementation files will need to know what the definition of Fn and Obj are.

So this doesn't compile:

1
2
3
4
5
6
7
8
//button.h

class Button {
...
template<typename Fn, typename Obj>
void addListener(Fn callback, Obj &object);
...
};

1
2
3
4
5
6
7
8
9
// button.cpp
...
template<typename Fn, typename Obj>
void Button::addListener(Fn callback, Obj &object) {
        boost::signals2::signal<void ()> signal;
	signal.connect(boost::bind(callback, object));
	signal(); // executes the callback
}
...


With the template definition included just above the method in button.cpp the compiler points out that it has already been defined in the header file. Without it, it doesn't know what Fn and Obj are. Presumably there still needs to be a reference to the template in the .cpp file but I can't see where.
You can't. Template aren't real functions so you need to have it defined entirely in the .h(pp) file.
Yes, I was beginning to realise this in some of the things I've read since posting. Not a huge problem I suppose.

Thanks for the help.
Topic archived. No new replies allowed.