0

I try to bind boost::asio arguments. Function to bind is static member of structure:

template <typename T>
struct bind_struct{

   typedef boost::system::error_code                         error_code;
   typedef boost::asio::ip::tcp::acceptor                    tcp_acceptor_type;
   typedef std::shared_ptr<boost::asio::ip::tcp::socket>     socket_type;


   static void tcp_on_async_accept(error_code& er,
                                  tcp_acceptor_type* acc,
                                  socket_type socket){
       std::cout << "ok" << std::endl;
   }
   static void good_function(int m){
       std::cout << m << std::endl;
   }


};

Bind operation:

  /*Error*/
  bind_struct<void>::socket_type sock;
  bind_struct<void>::tcp_acceptor_type* acc;
  auto fn = boost::bind(bind_struct<void>::tcp_on_async_accept,
                                                boost::asio::placeholders::error,
                                                acc, sock);
  fn();


  /*Ok*/
  auto fn1 = boost::bind(bind_struct<void>::good_function,_1);
  fn1(10);

What is a problem here? Errors.

crastinus
  • 133
  • 2
  • 10
  • `bind()` may be confused since you're trying to bind a member function without an object on which to call it (which in theory is OK, since the member is static). If you pass `&sock` as the second parameter to `bind()` does that change the errors? – Chad Jan 14 '14 at 06:12
  • @Chad smart_poiter by link it is normal? http://coliru.stacked-crooked.com/a/7615c6464bd2d488 – crastinus Jan 14 '14 at 06:52

1 Answers1

2

fn() fails because the functor expects the first argument passed to it to be able to bind to boost::system::error_code&.

The Boost.Asio documentation for boost::asio::placeholders::error states:

An argument placeholder, for use with boost::bind(), that corresponds to the error argument of a handler for any of the asynchronous functions.

Hence, when the function:

void bind_struct::tcp_on_async_accept(
    boost::system::error_code&,
    boost::asio::ip::tcp::acceptor*,
    std::shared_ptr<boost::asio::ip::tcp::socket>)

is bound with:

boost::asio::ip::tcp::acceptor* acceptor;
std::shared_ptr<boost::asio::ip::tcp::socket> socket;
auto fn = boost::bind(
    bind_struct<void>::tcp_on_async_accept,
    boost::asio::placeholders::error, // _1
    acceptor, socket);

The resulting functor fn can only be invoked when the first argument passed to its invocation can bind to boost::system::error_code&. Thus, the following will fail:

fn();

where as the following will work:

boost::system::error_code error;
fn(error);

Consider reading this blog for a great illustrated example of bind().


If bind_struct::tcp_on_async_accept() is going to be used as the handler to an async_accept() operation, then consider changing the first parameter type to accept error_code by value or by const reference. The Asynchronous Operations type requirements specifies that the first parameter for handlers is an lvalue of type boost::system::error_code, and the AcceptHandler documentation states if h is a handler and ec is a const error_code, then the expression h(ec) must be valid. As a const error_code cannot be bound to boost::system::error_code&, bind_struct::tcp_on_async_accept() fails to meet the AcceptHandler type requirement.

Tanner Sansbury
  • 51,153
  • 9
  • 112
  • 169
  • I'll find an error. Function must receve just const boost::asio::error_code&. But it useful information. – crastinus Jan 15 '14 at 04:20
  • 1
    @crastinus Per [AcceptHandler](http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/AcceptHandler.html) documentation, if `h` is a handler and `ec` is a const `error_code`, then the expression `h(ec)` must be valid. Hence, the function may accept `error_code` by value or by const reference. When using `bind()`, addition arguments may be bound to the function when constructing the functor. While `placeholders::error` (`_1`) may appear in the binding zero or multiple times, placeholders for different positions, such as `_2`, may not appear in the binding. – Tanner Sansbury Jan 15 '14 at 13:22