2.5.9 Argument Bindings

What was the problem

The bindings example from 2.5.8 was quite complex, and it does not even handle member functions. Since it is already using C++11 features, it is left to the reader to consider how to implement something equivalent with pre-C++11 features.

How the Problem is Solved

PIC <utility>

However, a better implementation of a binding is available in C++11, via std::bind(). This function creates a function object, of an unspecified type, that will forward its arguments to the bound function. This is something I would typically use in event handling.

struct message_queue { /*  */ }; 
struct message_counter 
  void count_message(); 
void connect_handlers(message_queue& queue) 
  message_counter counter; 
  // Here std::bind() creates a function object that calls 
  // counter.process_message() when invoked. 
  // Note that the arguments of the function object are deduced from 
  // the signature of message_dispatcher::count_message. 
  queue.on_message(std::bind(&message_counter::process_message, &counter)); 

Interestingly, it is also possible to either force the value of an argument, or to redirect an argument from the caller to a specific argument of the called.

struct message_queue { /*  */ }; 
void log_error(int queue_id, error e); 
void connect_error_handler(message_queue& queue, int queue_id) 
  // This one creates a function object accepting a single argument, 
  // that calls log_error(queue_id, e), for a given argument e. 
  // Note that we must explicitly tell what to do with the argument 
  // given by the caller here, via the placeholder. 
  queue.on_message(std::bind(&log_error, queue_id, std::placeholders::_1)); 

In the above code, std::placeholders::_1 tells std::bind to pass whatever is received as the first argument (because the _1) to the second argument of log_error (second because it is the second following the function when the binding is created).

Note that the standard does not define how many placeholders must be defined.