Reputation: 3308
I am writing an asynchronous function that accepts a callback fn to invoke after completion. In general this works fine (but with some limitations) and I am able to send params as below.
#include <boost/bind.hpp>
#include <iostream>
void foo_cb(int result, const char* data) {
std::cout << "foo_cb executed with params " << result << ", " << data << std::endl;
}
//void foo_caller(std::function<void(int, const char*)> ff) {
//template <typename... Args>
void foo_caller(std::function<void(int, const char*)> ff) {
std::cout << "Caller executing..." << std::endl;
ff(1, "hi");
}
int main(int argc, char** argv) {
int x = 122;
const char* y = "Hello nether world";
foo_caller(boost::bind(foo_cb, x, y));
return 0;
}
I have two issues here:
Inside foo_caller() function, while invoking callback ff, I have to give some dummy values to satisfy the function signature of called fn i.e. ff(1, "hi"); But this executes correctly and prints the original values passed in main(). It looks very unnatural having to call ff() with some values, which won't be used.
In my main(), I may decide to pass different types and/or numbers of arguments to the called-back function, and i write the the completion handler accordingly. In such case, how do I actually write the async function foo_caller(...) to take variable number of args and data types and correctly call the completion handler?
Update
Thanks to Jonesinator, after having looked at std::placeholders, I realized what mistake I was doing.
The updated version of code that works is, below:
void foo_cb(int result, const char* data) {
std::cout << "foo_cb executed with params " << result << ", " << data << std::endl;
}
void foo_caller(std::function<void(int, const char*)> ff, int a, const char* b) {
std::cout << "Caller executing..." << std::endl;
ff(a, b);
}
int main(int argc, char** argv) {
int x = 122;
const char* y = "Hello nether world";
foo_caller(std::bind(foo_cb, std::placeholders::_1, std::placeholders::_2), x, y);
return 0;
}
Upvotes: 2
Views: 341
Reputation: 46
For your first issue: since you bind the arguments to the function, foo_caller
's signature should be:
void foo_caller(std::function<void()> ff)
boost::bind copies the arguments you passed and creates a new callable entity that can be invoked with no arguments (since they're known by this new entity) and returns void.
When you want to pass arguments at a later time, you have to bind placeholders like Jonesinator explains in his answer.
Upvotes: 0
Reputation: 4216
Since you're using std::function
you should probably also use std::bind
. The std::bind
function can take placeholder arguments for arguments that are not bound at the time the std::function
is created.
Upvotes: 3