2

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:

  1. 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.

  2. 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.

  1. foo_caller signature n definition were wrong.
  2. Invocation from main was also wrong.

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;
}

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.