1

I am attempting to bind the first parameter of a variadic function using std::bind and then pass the returned functor to the connect() function of a boost::signals2::signal. The process works fine as long as the variadic function is not a member function. This is what I would like to be able to do:

class test {
public:
  test() {}

  void call_var_callback(string const& func, ...) { 
    va_list args;
    va_start(args, func);

    std::cout << "Calling variadic function: " << func << std::endl;
  }
};

test t;

void register_callback2(std::map<string, boost::any>& sig_table,
                        string func, string event) {

  auto event_entry = sig_table.find(event);
  if (event_entry != sig_table.end()) {

    if (event == "event1") {
      auto sig = boost::any_cast<signal<void (void)>*>(sig_table["event1"]);

      sig->connect(std::bind(&test::call_var_callback, &t, std::cref(func)));
      //           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    }

  } else {
    std::cout << "No such event exists!" << std::endl;
  }
}

int main( void ) {

  // define events
  signal<void (void)> event1;
  signal<void (char const*)> event2;
  signal<void (int, char const*)> event3;

  // intialize event / signal lookup table
  std::map<string, boost::any> sig_tbl;
  sig_tbl["event1"] = &event1;
  sig_tbl["event2"] = &event2;
  sig_tbl["event3"] = &event3;

  // connect the signals
  register_callback2(sig_tbl, "func1", "event1");
  register_callback2(sig_tbl, "func2", "event2");
  register_callback2(sig_tbl, "func3", "event3");

  // call the signals
  for (int i = 1000; i > 0; --i) {
    (*boost::any_cast<signal<void (void)>*>(sig_tbl["event1"]))();
    (*boost::any_cast<signal<void (char const*)>*>(sig_tbl["event2"]))("0xBAAD");
    (*boost::any_cast<signal<void (int, char const*)>*>(sig_tbl["event3"]))(5, "0xBEEF");
  }
}

When I compile I get an error that states there is "no match for call to ..." Where ... is the filled in templated type of the call to bind. If I move the definition of call_var_callback() outside the scope of the 'test' object, everything works. However, in my real code base I need the bound function to be a member of a class because it carries state along with it.

Thank you in advance for your consideration and assistance.

maaronking
  • 65
  • 7
  • 2
    So what's the problem? Mention the precise error or undesired runtime behaviour observed. Incidentally, in your example you are binding to the address of a local variable `t` which is destroyed at the end of `register_callback2`, leading to undefined behaviour when the signal is fired. – Oktalist Apr 30 '14 at 20:52
  • Thanks for the feedback. I have edited my question to hopefully make things a bit more clear. – maaronking Apr 30 '14 at 21:27
  • _Precise_ error please. – Oktalist Apr 30 '14 at 21:28

1 Answers1

1

When you bind member functions, you don't take the address of the object. In your code :

sig->connect(std::bind(&test::call_var_callback, &t, std::cref(func)));

the &t is wrong, it should be a plain t

bind supports 2 main ways of binding the object: You can

  • pass an object itself or
  • a pointer to object (as well as a shared pointer instead of a raw pointer)
Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153