I've created a minimal example to illustrate my question.
#include <iostream>
#include <memory>
#include <vector>
#include <functional>
class Bar {
public:
void bind_function(std::function<void(int)> callback){
m_callbacks.push_back(callback);
}
void invoke() {
for(auto& c : m_callbacks){
c(12345);
}
}
private:
std::vector<std::function<void(int)>> m_callbacks;
};
class Foo{
public:
void register_foo(){ m_msg.bind_function(std::bind(&Foo::callback_foo, this)); }
void callback_foo(/*int a*/){ std::cout << "callback foo invoked!!!!" << std::endl; }
void run() { m_msg.invoke(); }
private:
Bar m_msg;
};
int main(){
Foo foo;
foo.register_foo();
foo.run();
return 0;
}
I have a Bar
class where it has two methods: Bar::bind_function
to pass a function pointer to be pushed into some vector. And a Bar::invoke
method which will invoke the callbacks from the vector.
Then I have a Foo
which has three methods: A Foo::register_foo
method where I will invoke the Bar::bind_function
from Bar and the actual method to be invoked Foo::callback_foo
.
Finally a method to Foo::run
the registered functions.
The code compiles and I can see the callback/registered method being executed.
[QUESTION]
Why does the code compile if the function pointer from this vector:
std::vector<std::function<void(int)>> m_callbacks
Doesn't match the actual callback:
void callback_foo(/*int a*/){...}
One is void(int)
and the other is void()
.
If I uncomment my void callback_foo(/*int a*/){...}
to match void callback_foo(int a){...}
I get the following error:
error: static assertion failed: Wrong number of arguments for pointer-to-member
How can I fix this error?
error: static assertion failed: Wrong number of arguments for pointer-to-member
The problem here is in std::bind
. Since you added int a
as an parameter, Foo::callback(int)
now requires two arguments, and you only provided a Foo*
. You need to tell std::bind
what to do with the int a
parameter.
In this case, you need to tell std::bind
to not bind it. Instead, it should return a unitary functor (one unbound argument remaining). You do that by passing std::placeholders::_1
:
std::bind(&Foo::callback_foo, this, std::placeholders::_1);