Quick Q: When should you prefer std::function vs. a virtual function to implement a callback? -- SO

Save to:
Instapaper Pocket Readability

Quick A: Using a named abstract base class makes code more tightly coupled to that specific name. Where possible, prefer using std::function which is more general and flexible.

Recently on SO:

Pros & cons of a callback (std::function/std::bind) vs an interface (abstract class)

I'm creating a server application in C++11 using Boost.Asio. I've created a class, Server, which takes care of accepting new connections. It's basically just:

void Server::Accept() {
  socket_.reset(new boost::asio::ip::tcp::socket(*io_service_));
  acceptor_.async_accept(*socket_,
                         boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error));
}
void Server::HandleAccept(const boost::system::error_code& error) {
  if (!error) {
    // TODO
  } else {
    TRACE_ERROR("Server::HandleAccept: Error!");
  }
  Accept();
}

I've found two ways (I'm sure there are more) to "fix" the TODO comment, i.e. to move the socket to wherever it should go. In my case I just want it back to the class instance that owns the Server instance (which then wraps it in a Connection class and inserts it to a list).

  1. Server has a parameter in its constructor: std::function<void(socket)> OnAccept which is called in HandleAccept.
  2. I create an abstract class, IServerHandler or whatever, which has one virtual method OnAccept. Server takes IServerHandler as parameter in its constructor and the class instance owning the server instance extends IServerHandler and constructs Server with *this as parameter.

What are the pros and cons of option 1 vs option 2? Are there any better options? I'm having the same problem in my Connection class (OnConnectionClosed). Also, depending on how I decide to design the system, it might need a OnPacketReceived and OnPacketSent callback.

Add a Comment

Comments are closed.

Comments (0)

There are currently no comments on this entry.