Should std::bind be compatible with boost::asio?
Asked Answered
C

1

44

I am trying to adapt one of the boost::asio examples to use c++11 / TR1 libraries where possible. The original code looks like this:

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));
}

If I replace boost::bind with std::bind as follows:

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

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

I get a large error message, with ends with:

/usr/include/c++/4.4/tr1_impl/functional:1137: error: return-statement with a value, in function returning 'void'

I am using gcc version 4.4 with boost version 1.47

I expected boost::bind and std::bind to be interchangeable.

Cascabel answered 19/1, 2012 at 10:4 Comment(9)
std takes a lot from boost and tr1, but they're not the same. I wonder if this has something to do with this questionDyaus
a potentially related ticketTorytoryism
@Sam Miller I found the ticket but it has not been updated for 3 years! I have also tried this against v1.48 of boost, and using std::placeholders instead of the boost::asio::placeholders. For now I am sticking with boost::shared_ptr and boost::bind for the asio code.Cascabel
I remember having a similar problem a while back. Have you tried replacing boost::asio::placeholders::error with std::placeholders::_1 (or maybe _2)Lowery
If you have std::bind I'm guessing you have lambdas - in which case you could do something like: [=](const boost::system::error_code& error){ /*do code here or...*/ this->handle_accept(...)}. Personally I've stopped using bind altogether and I just write it as a lambda whether the lambda calls a function or does stuff inline. My thought is: Why use a library feature when there's a language feature that does the same thing? I know this wasn't your question, just my $0.02Trapani
@Dave - just personal preference - I prefer to use bind when calling an existing member function object, and use lambdas when existing functionality isn't already available. In this case the bind would capture this, and (AFAIK) the end result would be the same. Incidently the boost::phoenix library is very handy for creating lambdas it goes a lot further than C++11 lambdas (it supports polymorphic lambdas).Cascabel
I guess this question should be closed now?Nevile
@denisw I would close it but there is not a suitable reason when I click close, choices are "off-topic", "duplicate", "not a question", "too localized" or "not-constructive". What would you suggest?Cascabel
@Cascabel Put your solution into an answer and then accept it. It also means anyone looking for an answer for a similar problem won't just skip over the question because it's closed, not answered.Smriti
C
31

I now have a solution

The problem is that when I first tried to switch to std::bind and std::shared_ptr I was still using the boost::asio::placeholders with std::bind, this resulted in a large amount of template compiler errors, so I then tried to switch piecemeal.

I first tried switching just boost::shared_ptr to std::shared_ptr, this failed because boost::bind will not work with std::shared_ptr with out a specialisation of the template get_pointer<typename T> for std::shared_ptr (see: How to resolve conflict between boost::shared_ptr and using std::shared_ptr?).

After switching to std::shared_ptr I then switched to std::bind, this time using the std::placeholders, (thanks richard) the example code now compiles and works correctly.

In order to use std::bind with boost::asio make sure that std::shared_ptr and the std::placeholders are also used.

Cascabel answered 2/3, 2012 at 16:40 Comment(2)
Note that generally when switching from boost to std::bind, std::shared_ptr is not strictly required. Only the placeholders are necessary as std::bind will look for them specifically.Selfhood
Probably need to mention that boost::asio::placeholders::error needs to be replaced with std::placeholders::_1. See this post: https://mcmap.net/q/390057/-can-39-t-use-asio-placeholders-error-in-non-boost-version-of-asioHypothalamus

© 2022 - 2024 — McMap. All rights reserved.