Asynchronous operations in Asio all expect a function object argument, the completion handler, which they invoke when the asynchronous operation completes. The signature of the handler depends on the type of operation. For example, a handler posted using io_service::post() must have the signature:
while an asynchronous wait operation expects:
void handler(error_code ec);
and asynchronous read/write operations want:
void handler(error_code ec, size_t length);
Non-trivial applications will need to pass some context to the completion handler, such as a this pointer. One way to do this is to use a function object adapter like boost::bind, std::tr1::bind or (as of C++0x) std::bind.
Unfortunately, for many C++ programmers, bind represents a little bit of magic. This is not helped by the impenetrable compiler errors that confront you when you use it incorrectly. And, in my experience, the underlying concept (where some function arguments are bound up-front, while others are delayed until the point of call) can present quite a steep learning curve.
I have put together some diagrams to help explain how bind works. For clarity, I have taken a few liberties with C++ syntax (e.g. omitting the parameter types on the function call operator) and (over-)simplified bind's implementation. Finally, the examples are limited to those likely to be useful with Asio. Comments and suggestions welcome.
bind can be used to adapt a user-supplied function expecting one argument into a function object that takes zero arguments. The bound value (123 in this example) is stored in a function object and is automatically passed to the user-supplied function as required:
[ click images for full size ]
Binding an argument can be used to turn a class member function into a zero-argument function object. As you know, non-static member functions have an implicit this parameter. This means that an appropriate pointer needs to be bound into the function object:
Alternatively, the implicit this can be made explicit by adapting a member function into a function object taking one argument:
Function objects will often use both bound arguments and arguments supplied at the point of use. This can be done using member functions:
or non-member functions:
Sometimes the function object's point of use will supply arguments which are not required to call the target function. bind will automatically discard these surplus arguments:
The surplus argument(s) need not be the at the end of the function object signature:
Finally, bind allows you to the reorder arguments to adapt the target function to the necessary function object signature: