[Boost.Bind] Adding a single argument to an existing function, breaks the code.

Hi. I am experiencing some issues with boost::bind and I was hoping if anybody is willing to help me. The example is really simple: First I have a function: void com_client::handle_init( const std::string& host, const command_t command) { boost::asio::ip::tcp::resolver resolver(connection_.socket().io_service()); boost::asio::ip::tcp::resolver::query query(host, service_); boost::asio::ip::tcp::resolver::iterator endpoint_iterator; endpoint_iterator = resolver.resolve(query); boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; connection_.socket().async_connect(endpoint, boost::bind( &com_client::handle_connect, this, 2, boost::asio::placeholders::error, ++endpoint_iterator) ); } After successful handshake, this function is called: void com_client::handle_connect( command_t command, const boost::system::error_code& e, boost::asio::ip::tcp::resolver::iterator endpoint_iterator) { if (!e) { rLog(com_client_control_, "Connection established with remote end-point %s.", connection_.socket().remote_endpoint().address().to_string().c_str()); command_ = DEPOSIT_CHUNK; connection_.async_write(command_, boost::bind( &com_client::handle_write_cmd, this, boost::asio::placeholders::error) ); } else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) { connection_.socket().close(); boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; connection_.socket().async_connect(endpoint, boost::bind( &com_client::handle_connect, this, boost::asio::placeholders::error, ++endpoint_iterator)); } else { std::cerr << e.message() << std::endl; } } This issue is when I modify the code such that connection_.socket().async_connect(endpoint, boost::bind( &com_client::handle_connect, this, //2, boost::asio::placeholders::error, ++endpoint_iterator) ); void com_client::handle_connect( //command_t command, const boost::system::error_code& e, boost::asio::ip::tcp::resolver::iterator endpoint_iterator) { one of the arguments is removed code compiles. And also: enum command_t { DEPOSIT_CHUNK = 2, DETRIEVE_CHUNK = 4, HEARTBEAT = 16 }; I was hoping if somebody could explain this. I've attached g++ output. -V

AMDG Vjekoslav Brajkovic wrote:
This issue is when I modify the code such that
connection_.socket().async_connect(endpoint, boost::bind( &com_client::handle_connect, this, //2, boost::asio::placeholders::error, ++endpoint_iterator) ); <snip>
enum command_t { DEPOSIT_CHUNK = 2, DETRIEVE_CHUNK = 4, HEARTBEAT = 16 };
I was hoping if somebody could explain this. I've attached g++ output.
You can't convert from int to command_t implicitly. Does it work if you pass DEPOSIT_CHUNK instead of 2? In Christ, Steven Watanabe

On Thu, 3 Jul 2008, Steven Watanabe wrote:
You can't convert from int to command_t implicitly. Does it work if you pass DEPOSIT_CHUNK instead of 2?
Unfortunately not. Initially I was passing <command_t command> from handle_init(), but then I decided to put value 2, so that I can isolate the issue. -V

AMDG Vjekoslav Brajkovic wrote:
On Thu, 3 Jul 2008, Steven Watanabe wrote:
You can't convert from int to command_t implicitly. Does it work if you pass DEPOSIT_CHUNK instead of 2?
Unfortunately not. Initially I was passing <command_t command> from handle_init(), but then I decided to put value 2, so that I can isolate the issue.
Does it work if you use mem_fn? boost::bind( boost::mem_fn(&com_client::handle_connect), this, 2, boost::asio::placeholders::error, ++endpoint_iterator) How about an explicit return type? boost::bind<void>( &com_client::handle_connect, this, 2, boost::asio::placeholders::error, ++endpoint_iterator) In Christ, Steven Watanabe

On Thu, 3 Jul 2008, Steven Watanabe wrote:
Does it work if you use mem_fn?
boost::bind( boost::mem_fn(&com_client::handle_connect), this, 2, boost::asio::placeholders::error, ++endpoint_iterator)
How about an explicit return type?
boost::bind<void>( &com_client::handle_connect, this, 2, boost::asio::placeholders::error, ++endpoint_iterator)
Nope. Same errors. I've tried both suggestions and their combinations with no success. V

AMDG Vjekoslav Brajkovic wrote:
On Thu, 3 Jul 2008, Steven Watanabe wrote:
Does it work if you use mem_fn?
boost::bind( boost::mem_fn(&com_client::handle_connect), this, 2, boost::asio::placeholders::error, ++endpoint_iterator)
How about an explicit return type?
boost::bind<void>( &com_client::handle_connect, this, 2, boost::asio::placeholders::error, ++endpoint_iterator)
Nope. Same errors. I've tried both suggestions and their combinations with no success.
Exactly the same errors? Including the third line of the error message? I've marked that parts I would expect to be different. /usr/local/include/boost-1_35/boost/bind/bind_template.hpp:15: instantiated from ‘boost::_bi::bind_t< **boost::_bi::unspecified** // void?? , void (com_client::*)(command_t, const boost::system::error_code&, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>), //Something involving _mfi::?? ^^^^^^^^^^^ boost::_bi::list3<boost::_bi::value<com_client*>, boost::arg<1> (*)(), boost::_bi::value<boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>
’
What is the type of boost::mem_fn(&com_client::handle_connect)? I usually get this information using #include <boost/mpl/assert.hpp> #include <boost/type_traits/is_same.hpp> BOOST_MPL_ASSERT((boost::is_same<__typeof__(boost::mem_fn(&com_client::handle_connect)), void>)); In Christ, Steven Watanabe

On Thu, 3 Jul 2008, Steven Watanabe wrote:
Exactly the same errors? Including the third line of the error message? I've marked that parts I would expect to be different.
/usr/local/include/boost-1_35/boost/bind/bind_template.hpp:15: instantiated from ?boost::_bi::bind_t< **boost::_bi::unspecified** // void?? , void (com_client::*)(command_t, const boost::system::error_code&, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>), //Something involving _mfi::?? ^^^^^^^^^^^ boost::_bi:: list3<boost::_bi::value<com_client*>, boost::arg<1> (*)(), boost::_bi:: value<boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>
?
Thank you for taking your time to solve my problem. I've reproduced the output. Apparently, all of the outputs are the same. ------------------------------------------------------- core dev/uleDFS/uleDFS% diff original.txt explicit.txt core dev/uleDFS/uleDFS% diff original.txt mem_fn.txt -------------------------------------------------------
What is the type of boost::mem_fn(&com_client::handle_connect)? I usually get this information using
# include <boost/mpl/assert.hpp> # include <boost/type_traits/is_same.hpp>
BOOST_MPL_ASSERT((boost::is_same<__typeof__(boost::mem_fn(&com_client::handle_connect)), void>)) ;
I've added the code with the following results: ---------------------------------------------------------------------- ../intercom/com_client.cpp:40: error: no matching function for call to âassertion_failed(mpl_::failed************ boost::is_same<boost::_mfi::mf3<void, com_client, command_t, const boost::system::error_code&, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp> >, void>::************)â ---------------------------------------------------------------------- Since I am not familiar with static assertion macros, I have no clue why it is complaining about 'no matching function for call'. -V

AMDG Vjekoslav Brajkovic wrote:
I've reproduced the output. Apparently, all of the outputs are the same.
Hmm. Interesting.
I've added the code with the following results:
---------------------------------------------------------------------- ../intercom/com_client.cpp:40: error: no matching function for call to ‘assertion_failed(mpl_::failed************ boost::is_same<boost::_mfi::mf3<void, com_client, command_t, const boost::system::error_code&, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>
, void>::************)’
Since I am not familiar with static assertion macros, I have no clue why it is complaining about 'no matching function for call'.
The point was to produce an error message that contains the type: boost::_mfi::mf3<void, com_client, command_t, const boost::system::error_code&, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>
This is the correct type, so I have no idea what's going on. Do you have a complete program that you can post which reproduces the error? Also, what version of gcc are you using? One more thing to try: BOOST_MPL_ASSERT((boost::is_same<__typeof__(boost::bind( &com_client::handle_connect, this, 2, boost::asio::placeholders::error, ++endpoint_iterator)), void>)) ; In Christ, Steven Watanabe

AMDG Vjekoslav Brajkovic wrote:
Thank you for taking your time to solve my problem.
I just realized what's going on. Take a look in the handle_client function, there's a second call to bind with handle_client. That's where the problem is. You should pass a command_t in both places. connection_.socket().async_connect(endpoint, boost::bind( &com_client::handle_connect, this, boost::asio::placeholders::error, ++endpoint_iterator)); In Christ, Steven Watanabe

On Thu, 3 Jul 2008, Steven Watanabe wrote:
I just realized what's going on.
Take a look in the handle_client function, there's a second call to bind with handle_client. That's where the problem is. You should pass a command_t in both places.
connection_.socket().async_connect(endpoint, boost::bind( &com_client::handle_connect, this, boost::asio::placeholders::error, ++endpoint_iterator));
Wow. I cannot believe it. I am sorry if I have wasted your time. Once again, I really appreciate your help. Best, -V
participants (2)
-
Steven Watanabe
-
Vjekoslav Brajkovic