I was making some modifications to a boost::asio
project today and I ran into a confusing compilation error when attempting to pass a bound function into an async call.
I have spent hours fiddling with this code, so I suspect I am missing something stupid. I would appreciate anyone who can point out where I am going wrong.
error: no match for call to ‘(boost::_mfi::mf3<void, ClientServerManager,
const MCServer&, boost::shared_ptr<Connection>,
const boost::system::error_code&>) (ClientServerManager*&,
MCServer&, boost::shared_ptr<Connection>&,
const MCServer&)’
Notice that const MCServer&
appears twice? That isn't how my bind statement is written:
void ClientServerManager::onConnect(const MCServer& server_info,
boost::shared_ptr<Connection> con,
const boost::system::error_code& err,
tcp::resolver::iterator i) {
// Instruct utility to do some work, and call our function when complete.
con->statusPing(
boost::bind( // <-- OFFENDING CODE
&ClientServerManager::onPingCompletion,
this,
server_info,
con, // shared_ptr to connection (maintains scope)
boost::asio::placeholders::error // in case of a downstream failure
)
);
}
In the Connection header statusPing(...)
is defined as follows:
void statusPing(boost::function<
void(
MCServer&, boost::shared_ptr<Connection>,
const boost::system::error_code&
)>);
The handler eventually to be called:
void ClientServerManager::onPingCompletion(
const MCServer& server_info,
boost::shared_ptr<Connection>,
const boost::system::error_code& err){
// Use the results to drive some function...
}
Background:
- I have a class which iterates through a list of servers and opens short-lived connections with them to make sure they are operating properly.
- The class uses a utility,
Connection
which inheritsboost::enable_shared_from_this.
Therefore, I call a function,Connection::create(..)
to grab aboost::shared_ptr
to start work with. When any async calls are made, this pointer has to be passed to keep the connection in scope. - In this instance after the connection is successfully established, I want to pass execution to
Connection
such that it can execute some tasks, and I want it to call a handle once those tasks are complete. I cannot get boost::bind to compile properly in this case. - Now the issue I am having is that the
boost::bind
might be linked to the use of theboost::asio::placeholders::error
template.
The full output follows:
g++ -std=c++0x -DBOOST_LOG_DYN_LINK -I/home/donald/Desktop/workspace/MCProxy/Debug/ -O3 -march=corei7-avx -g1 -w -c -fmessage-length=0 -MMD -MP -MF"src/ClientServerManager.d" -MT"src/ClientServerManager.d" -o "src/ClientServerManager.o" "../src/ClientServerManager.cpp"
In file included from ....
/boost/bind/bind.hpp: In instantiation of ‘void boost::_bi::list4<A1, A2, A3, A4>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>; A = boost::_bi::list3<const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>; A1 = boost::_bi::value<ClientServerManager*>; A2 = boost::_bi::value<MCServer>; A3 = boost::_bi::value<boost::shared_ptr<Connection> >; A4 = boost::arg<1> (*)()]’:
/boost/bind/bind_template.hpp:116:59: required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1&, A2&, A3&) [with A1 = const MCServer; A2 = boost::shared_ptr<Connection>; A3 = const boost::system::error_code; R = void; F = boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>; L = boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()>; boost::_bi::bind_t<R, F, L>::result_type = void]’
/boost/function/function_template.hpp:153:11: required from ‘static void boost::detail::function::void_function_obj_invoker3<FunctionObj, R, T0, T1, T2>::invoke(boost::detail::function::function_buffer&, T0, T1, T2) [with FunctionObj = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; T0 = const MCServer&; T1 = boost::shared_ptr<Connection>; T2 = const boost::system::error_code&]’
/boost/function/function_template.hpp:934:60: required from ‘void boost::function3<R, T1, T2, T3>::assign_to(Functor) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; T0 = const MCServer&; T1 = boost::shared_ptr<Connection>; T2 = const boost::system::error_code&]’
/boost/function/function_template.hpp:722:7: required from ‘boost::function3<R, T1, T2, T3>::function3(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; T0 = const MCServer&; T1 = boost::shared_ptr<Connection>; T2 = const boost::system::error_code&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/boost/function/function_template.hpp:1071:16: required from ‘boost::function<R(T0, T1, T2)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; T0 = const MCServer&; T1 = boost::shared_ptr<Connection>; T2 = const boost::system::error_code&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
../src/ClientServerManager.cpp:90:3: required from here
/boost/bind/bind.hpp:457:9: error: no match for call to ‘(boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>) (ClientServerManager*&, MCServer&, boost::shared_ptr<Connection>&, const MCServer&)’
In file included ....
/boost/bind/mem_fn_template.hpp:366:85: note: candidates are:
/boost/bind/mem_fn_template.hpp:391:7: note: R boost::_mfi::mf3<R, T, A1, A2, A3>::operator()(T*, A1, A2, A3) const [with R = void; T = ClientServerManager; A1 = const MCServer&; A2 = boost::shared_ptr<Connection>; A3 = const boost::system::error_code&]
/boost/bind/mem_fn_template.hpp:391:7: note: no known conversion for argument 4 from ‘const MCServer’ to ‘const boost::system::error_code&’
/boost/bind/mem_fn_template.hpp:396:25: note: template<class U> R boost::_mfi::mf3::operator()(U&, A1, A2, A3) const [with U = U; R = void; T = ClientServerManager; A1 = const MCServer&; A2 = boost::shared_ptr<Connection>; A3 = const boost::system::error_code&]
/boost/bind/mem_fn_template.hpp:396:25: note: template argument deduction/substitution failed:
In file included ....
/boost/bind/bind.hpp:457:9: note: cannot convert ‘(& a)->boost::_bi::list3<A1, A2, A3>::operator[]<const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>(boost::_bi::storage4<A1, A2, A3, boost::arg<I> (*)()>::a4_<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, 1>)’ (type ‘const MCServer’) to type ‘const boost::system::error_code&’
In file included ....
/boost/bind/mem_fn_template.hpp:404:25: note: template<class U> R boost::_mfi::mf3::operator()(const U&, A1, A2, A3) const [with U = U; R = void; T = ClientServerManager; A1 = const MCServer&; A2 = boost::shared_ptr<Connection>; A3 = const boost::system::error_code&]
/boost/bind/mem_fn_template.hpp:404:25: note: template argument deduction/substitution failed:
In file included ....
/boost/bind/bind.hpp:457:9: note: cannot convert ‘(& a)->boost::_bi::list3<A1, A2, A3>::operator[]<const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>(boost::_bi::storage4<A1, A2, A3, boost::arg<I> (*)()>::a4_<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, 1>)’ (type ‘const MCServer’) to type ‘const boost::system::error_code&’
In file included from ....
/boost/bind/mem_fn_template.hpp:412:7: note: R boost::_mfi::mf3<R, T, A1, A2, A3>::operator()(T&, A1, A2, A3) const [with R = void; T = ClientServerManager; A1 = const MCServer&; A2 = boost::shared_ptr<Connection>; A3 = const boost::system::error_code&]
/boost/bind/mem_fn_template.hpp:412:7: note: no known conversion for argument 1 from ‘ClientServerManager*’ to ‘ClientServerManager&’
Edit: (boost::function<void(...)>
-> boost::function<void()>
)
Per suggestion, I changed the Connection
function to read void statusPing(boost::function<void()>);
as the parameters are bound in. This change yields a different error:
g++ -std=c++0x -DBOOST_LOG_DYN_LINK -I/home/donald/Desktop/workspace/MCProxy/Debug/ -O3 -march=corei7-avx -g1 -w -c -fmessage-length=0 -MMD -MP -MF"src/ClientServerManager.d" -MT"src/ClientServerManager.d" -o "src/ClientServerManager.o" "../src/ClientServerManager.cpp"
In file included from ....
/boost/bind/bind.hpp: In instantiation of ‘void boost::_bi::list4<A1, A2, A3, A4>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>; A = boost::_bi::list0; A1 = boost::_bi::value<ClientServerManager*>; A2 = boost::_bi::value<MCServer>; A3 = boost::_bi::value<boost::shared_ptr<Connection> >; A4 = boost::arg<1> (*)()]’:
/boost/bind/bind_template.hpp:20:59: required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()() [with R = void; F = boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>; L = boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()>; boost::_bi::bind_t<R, F, L>::result_type = void]’
/boost/function/function_template.hpp:153:11: required from ‘static void boost::detail::function::void_function_obj_invoker0<FunctionObj, R>::invoke(boost::detail::function::function_buffer&) [with FunctionObj = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void]’
/boost/function/function_template.hpp:934:60: required from ‘void boost::function0<R>::assign_to(Functor) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void]’
/boost/function/function_template.hpp:722:7: required from ‘boost::function0<R>::function0(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/boost/function/function_template.hpp:1071:16: required from ‘boost::function<R()>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
../src/ClientServerManager.cpp:90:2: required from here
/boost/bind/bind.hpp:457:9: error: no match for ‘operator[]’ in ‘a[boost::_bi::storage4<A1, A2, A3, boost::arg<I> (*)()>::a4_<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, 1>]’
/boost/bind/bind.hpp:457:9: note: candidates are:
In file included ....
/boost/bind/bind.hpp:170:27: note: template<class T> T& boost::_bi::list0::operator[](boost::_bi::value<T>&) const
/boost/bind/bind.hpp:170:27: note: template argument deduction/substitution failed:
In file included ....
/boost/bind/bind.hpp:457:9: note: mismatched types ‘boost::_bi::value<T>’ and ‘boost::arg<1>()’
In file included ....
/boost/bind/bind.hpp:172:33: note: template<class T> const T& boost::_bi::list0::operator[](const boost::_bi::value<T>&) const
/boost/bind/bind.hpp:172:33: note: template argument deduction/substitution failed:
In file included ....
/boost/bind/bind.hpp:457:9: note: mismatched types ‘const boost::_bi::value<T>’ and ‘boost::arg<1>()’
In file included ....
/boost/bind/bind.hpp:174:27: note: template<class T> T& boost::_bi::list0::operator[](const boost::reference_wrapper<T>&) const
/boost/bind/bind.hpp:174:27: note: template argument deduction/substitution failed:
In file included from ....
/boost/bind/bind.hpp:457:9: note: mismatched types ‘const boost::reference_wrapper<T>’ and ‘boost::arg<1>()’
In file included from ....
/boost/bind/bind.hpp:176:76: note: template<class R, class F, class L> typename boost::_bi::result_traits<R, F>::type boost::_bi::list0::operator[](boost::_bi::bind_t<R, F, L>&) const
/boost/bind/bind.hpp:176:76: note: template argument deduction/substitution failed:
In file included from ....
/boost/bind/bind.hpp:457:9: note: mismatched types ‘boost::_bi::bind_t<R, F, L>’ and ‘boost::arg<1>()’
/boost/bind/bind.hpp:178:76: note: template<class R, class F, class L> typename boost::_bi::result_traits<R, F>::type boost::_bi::list0::operator[](const boost::_bi::bind_t<R, F, L>&) const
/boost/bind/bind.hpp:178:76: note: template argument deduction/substitution failed:
/boost/bind/bind.hpp:457:9: note: mismatched types ‘const boost::_bi::bind_t<R, F, L>’ and ‘boost::arg<1>()’
make: *** [src/ClientServerManager.o] Error 1
A simplified example:
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <boost/function.hpp>
class ExampleWorker {
public:
void statusPing(boost::function<void()> f){
// Do work.
f(); // Call handle
}
};
class SomeObject {};
void someHandle(boost::shared_ptr<SomeObject> obj,
const boost::system::error_code& err){
// ...
}
int main() {
ExampleWorker* e = new ExampleWorker();
boost::shared_ptr<SomeObject> ptr(new SomeObject());
e->statusPing(
boost::bind(
&someHandle,
ptr,
boost::asio::placeholders::error
)
);
}