Can't use asio::placeholders::error in non-Boost version of Asio

后端 未结 1 1915
一整个雨季
一整个雨季 2021-02-15 15:45

I\'m trying to use the non Boost version of Asio in a project. I\'m writing a callback to stream_protocol::acceptor::async_accept. The signature requires asio

相关标签:
1条回答
  • 2021-02-15 16:31

    In short, use std::placeholders::_1 instead of asio::placeholders:error.


    Asio only supports the convenient placeholder variables when using Boost.Bind. The error placeholder documentation states:

    An argument placeholder, for use with boost::bind(), ...

    When using std::bind() to create handlers, one needs to use std::bind's placeholders. The async_accept() operation accepts a handler that meets the AcceptHandler type requirements:

    An accept handler must meet the requirements for a handler. A value h of an accept handler class should work correctly in the expression h(ec), where ec is an lvalue of type const error_code.

    When creating a functor with std::bind() to function as a AcceptHandler, if one wishes to obtain the error_code argument, then use std::placeholders::_1:

    void handle_accept(const std::error_code&);
    
    acceptor.async_accept(server_socket, std::bind(&handle_accept,
      std::placeholders::_1 /* error_code */));
    

    Here is a complete minimal example demonstrating using std::bind(). Note that coliru does not appear to have an Asio standalone version available, but the example should suffice:

    #include <iostream>
    #include <functional>
    
    #include <boost/asio.hpp>
    
    void handle_accept(const boost::system::error_code& error_code)
    {
      std::cout << "handle_accept: " << error_code.message() << std::endl;
    }
    
    void noop() {}
    
    int main()
    {
      using boost::asio::ip::tcp;
      boost::asio::io_service io_service;
    
      // Create all I/O objects.
      tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
      tcp::socket server_socket(io_service);
      tcp::socket client_socket(io_service);
    
      // Connect client and server sockets.
      acceptor.async_accept(server_socket, std::bind(&handle_accept,
        std::placeholders::_1 /* error_code */));
      client_socket.async_connect(acceptor.local_endpoint(), std::bind(&noop));
      io_service.run();
    }
    

    Output:

    handle_accept: Success
    

    Optionally, if one wishes for a bit more verbosity, then named placeholders could be used:

    namespace asio_placeholders
    {
      auto error = std::placeholders::_1;
    }
    
    // ...
    
    acceptor.async_accept(server_socket, std::bind(&handle_accept,
      asio_placeholders::error));
    

    The unspecified type observed in the source code is only used when generating documentation, as shown in this code:

    #if defined(GENERATING_DOCUMENTATION)
    
    /// An argument placeholder, for use with boost::bind(), that corresponds to
    /// the error argument of a handler for any of the asynchronous functions.
    unspecified error;
    
    // ...
    
    #elseif
    
    0 讨论(0)
提交回复
热议问题