Search code examples
c++socketsboostboost-asio

How to register a function member as callback for boost::asio::ip::tcp::acceptor::async_accept()?


I can register a freestanding function as async_accept() callback like so:

void accept_cb(const boost::system::error_code& error, boost::asio::ip::tcp::socket socket)
{
    // do stuff
}

[...]

_acceptor.async_accept(accept_cb); // successfull calls the function above

However, I'd like to turn accept_cb() into a class function member and am unable to register it with async_accept().

void tcp_server::accept_cb(const boost::system::error_code& error, boost::asio::ip::tcp::socket socket)

[...]

_acceptor.async_accept(boost::bind(&tcp_server::accept_cb, this, boost::asio::placeholders::error, boost::placeholders::_1)); // does not compile
_acceptor.async_accept(boost::bind(&tcp_server::accept_cb, this, boost::asio::placeholders::error, boost::placeholders::_2)); // does not compile
_acceptor.async_accept(boost::bind(&tcp_server::accept_cb, this, boost::placeholders::_1, boost::placeholders::_2)); // does not compile

What is the right syntax to use here?

I learned about boost::asio::placeholders::error from an official boost asio example and about boost::placeholders::_1 and ::_2 from the boost help page on bind().


Solution

  • You can register a class function member as callback for boost::asio::ip::tcp::acceptor::async_accept() (Boost version 1.74) like so:

    _acceptor.async_accept(std::bind(&tcp_server::accept_cb, this, std::placeholders::_1, std::placeholders::_2));
    

    Note the use of stdlib instead of boost.

    This is in accordance with the documentation, which states that

    • the callback must be a MoveAcceptHandler, and that
    • adapting non-static class member functions to MoveAcceptHandlers can be done using std::bind().
    • Support of boost::bind() is not specifically mentioned and indeed doesn't seem to work as indicated by the question.