1

It is specified in boost::asio document that a handler for async_accept() must satisfy the following function signature:

void accept_handler(
    const boost::system::error_code& ec)
{
  ...
}

However, in the Daytime.3 example, using boost::bind, the handler can be specified as much parameter as desired, as long as it does not exceed the limit of boost::bind (which is 9 arguments at maximum):

class tcp_server
{
public:
  tcp_server(boost::asio::io_service& io_service)
    : acceptor_(io_service, tcp::endpoint(tcp::v4(), 13))
  {
    start_accept();
  }

private:
  void start_accept()
  {
    tcp_connection::pointer new_connection =
      tcp_connection::create(acceptor_.get_io_service());

    acceptor_.async_accept(new_connection->socket(),
        boost::bind(&tcp_server::handle_accept, this, new_connection,
          boost::asio::placeholders::error));
  }

  void handle_accept(tcp_connection::pointer new_connection,
      const boost::system::error_code& error)
  {
    if (!error)
    {
      new_connection->start();
    }

    start_accept();
  }

  tcp::acceptor acceptor_;
};

Why is that possible? I thought even with boost::bind, the exact function signature still has to be matched.

Notice the handle_accept() funciton and how it is used in async_accept(). The full code listing is here.

Sam Miller
  • 23,808
  • 4
  • 67
  • 87
Amumu
  • 17,924
  • 31
  • 84
  • 131

2 Answers2

3

I found the real answer here: http://blog.think-async.com/2010/04/bind-illustrated.html Basically, the real function is called underlying the function call operator (). boost::bind creates a function object, pretend to be the function signature required to be a parameter for some other functions. Using boost::bind, additional information can be passed into the handler.

Amumu
  • 17,924
  • 31
  • 84
  • 131
1

This concept is described in the timer tutorial 3, it's how bind works.

In this example, the boost::asio::placeholders::error argument to boost::bind() is a named placeholder for the error object passed to the handler. When initiating the asynchronous operation, and if using boost::bind(), you must specify only the arguments that match the handler's parameter list. In tutorial Timer.4 you will see that this placeholder may be elided if the parameter is not needed by the callback handler.

Specific to your question with async_accept, the error_code parameter is passed to the bound function object as a named parameter. However, you are not required to use that parameter. As the above paragraph indicates, it may be elided. Additional parameters may be provided as well, this can give your handler more information about the asynchronous operation that triggered it.

Sam Miller
  • 23,808
  • 4
  • 67
  • 87
  • By reading carefully this guide: http://en.highscore.de/cpp/boost/index.html (Function Object part), I figured out. Thanks for you answer, although it's correct but still not sufficient. I was wondering why `bind` can turn 2 or more parameters functions into the required function object/pointer with less parameters. – Amumu Dec 19 '11 at 19:09