problems with nested boost::bind and boost::asio

Hi, I use async_read of boost::asio to receive network data. After a complete 'packet' was read (which needs 2 async read calls) I want to call a user defined handler. Therefore, I introduced a new templater parameter in my callback methods. Unfortunately, my code ends in a compile error. If I outcomment the handler call, than it compiles fine. But with the call of the handler object, I got a conversion error. At first I want to describe my code on some excerpts: ---------------------------------------------------------------------------------------- In 'startProcessing' I use perfect forwarding for the callback object. template<typename T> void startProcessing(T&& handler,bool activateNoDelay = true) { // m_socket.set_option(asio::ip::tcp::no_delay(activateNoDelay )); // startAsyncRead(std::forward<T>(handler)); } ---------------------------------------------------------------------------------------- 'startAsynRead' has two overloads. One for boost::bind objects and one for all other. The boost bind objects are encased with boost::protect to prevent an evaluation of boost::bind in the later binds. // template<typename T> void startAsyncRead(T handler) { startAsyncReadImpl(handler); } //overload for boost bind objects necessary template<typename R, typename F, typename L> void startAsyncRead(boost::_bi::bind_t<R, F, L> handler) { startAsyncReadImpl(boost::protect(handler)); } ---------------------------------------------------------------------------------------- 'startAsyncReadImpl' calls asio::async_read and uses boost::bind to commit the handler object as a third parameter. // template<typename T> void startAsyncReadImpl(T&& handler) { //at first we need to read the header information auto& buf = m_headerInBuffer.getBuffer(); boost::asio::async_read( m_socket, boost::asio::buffer(buf.begin(), buf.size()), boost::asio::transfer_exactly(buf.size()), boost::bind(&CMessageChannel::handleAsyncReadHeader<T>, this,_1, _2, std::forward<T>(handler)) ); } ---------------------------------------------------------------------------------------- 'handleAsyncReadHeader' does some stuff and than calls asio::async_read with another method. // template<typename T> void handleAsyncReadHeader(const boost::system::error_code& error, std::size_t bytes_transferred, T handler) { . . . boost::asio::async_read( m_socket, boost::asio::buffer(buf.begin(), buf.size()), boost::asio::transfer_exactly(size), boost::bind(&CMessageChannel::handleAsyncReadBody<T>, this, _1, _2,handler) ); } ---------------------------------------------------------------------------------------- Finally, 'handleAsyncReadBody' has to do the wished call of the handler. // template<typename T> inline void CMessageChannel::handleAsyncReadBody(const boost::system::error_code& error, std::size_t bytes_transferred, T handler) { ... handler(Packet(m_headerInBuffer.getShort(4), bytes_transferred, m_currReadBuffer)); } ---------------------------------------------------------------------------------------- And here a call of start process: void testPacket(Packet& packet) {} . . . conn->startProcessing(boost::bind(&CMessageServer::testPacket, this, _1)); ---------------------------------------------------------------------------------------- I use Visual Studio 2013 and got the following error message: 1>D:\libraries\cpp\boost\boost_1_55_0\boost/bind/bind.hpp(313): error C2664: 'void boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>::operator ()(T *,A1) const' : Konvertierung von Argument 2 von 'const tuc::nw::Packet' in 'tuc::nw::Packet &' nicht möglich -> can't convert argument 2 'const tuc::nw::Packet' to tuc::nw::Packet & I never use const in my call chain. It seems that boost::protect introduces the const for the parameter. And I have no idea how to fix it :( ---------------------------------------------------------------------------------------- Here is the complete error message: 1>------ Erstellen gestartet: Projekt: network, Konfiguration: Release Win32 ------ 1> MessageChannel.cpp 1> MessageServer.cpp 1>D:\libraries\cpp\boost\boost_1_55_0\boost/bind/bind.hpp(313): error C2664: 'void boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>::operator ()(T *,A1) const' : Konvertierung von Argument 2 von 'const tuc::nw::Packet' in 'tuc::nw::Packet &' nicht möglich 1> with 1> [ 1> T=tuc::nw::CMessageServer 1> , A1=tuc::nw::Packet & 1> ] 1> Durch die Konvertierung gehen Qualifizierer verloren 1> D:\libraries\cpp\boost\boost_1_55_0\boost/bind/bind_template.hpp(47): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>::operator ()<F,boost::_bi::list1<const A1 &>>(boost::_bi::type<void>,F &,A &,int)". 1> with 1> [ 1> T=tuc::nw::CMessageServer * 1> , F=boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &> 1> , A1=tuc::nw::Packet 1> , A=boost::_bi::list1<const tuc::nw::Packet &> 1> ] 1> D:\libraries\cpp\boost\boost_1_55_0\boost/bind/bind_template.hpp(47): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>::operator ()<F,boost::_bi::list1<const A1 &>>(boost::_bi::type<void>,F &,A &,int)". 1> with 1> [ 1> T=tuc::nw::CMessageServer * 1> , F=boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &> 1> , A1=tuc::nw::Packet 1> , A=boost::_bi::list1<const tuc::nw::Packet &> 1> ] 1> D:\libraries\cpp\boost\boost_1_55_0\boost/bind/protect.hpp(60): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void boost::_bi::bind_t<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>>::operator ()<A1>(const A1 &)". 1> with 1> [ 1> T=tuc::nw::CMessageServer * 1> , A1=tuc::nw::Packet 1> ] 1> D:\libraries\cpp\boost\boost_1_55_0\boost/bind/protect.hpp(60): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void boost::_bi::bind_t<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>>::operator ()<A1>(const A1 &)". 1> with 1> [ 1> T=tuc::nw::CMessageServer * 1> , A1=tuc::nw::Packet 1> ] 1> G:\Quellcode\nc-programming\nc-libs\nc-libs/network/MessageChannel.h(196): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void boost::_bi::protected_bind_t<boost::_bi::bind_t<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>>>::operator ()<tuc::nw::Packet>(const A1 &)". 1> with 1> [ 1> T=tuc::nw::CMessageServer * 1> , A1=tuc::nw::Packet 1> ] 1> G:\Quellcode\nc-programming\nc-libs\nc-libs/network/MessageChannel.h(196): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void boost::_bi::protected_bind_t<boost::_bi::bind_t<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>>>::operator ()<tuc::nw::Packet>(const A1 &)". 1> with 1> [ 1> T=tuc::nw::CMessageServer * 1> , A1=tuc::nw::Packet 1> ] 1> G:\Quellcode\nc-programming\nc-libs\nc-libs/network/MessageChannel.h(179): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void tuc::nw::CMessageChannel::handleAsyncReadBody<T>(const boost::system::error_code &,size_t,T)". 1> with 1> [ 1> T=boost::_bi::protected_bind_t<boost::_bi::bind_t<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<tuc::nw::CMessageServer *>,boost::arg<1>>>> 1> ] 1> G:\Quellcode\nc-programming\nc-libs\nc-libs/network/MessageChannel.h(127): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void tuc::nw::CMessageChannel::handleAsyncReadHeader<T>(const boost::system::error_code &,size_t,T)". 1> with 1> [ 1> T=boost::_bi::protected_bind_t<boost::_bi::bind_t<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<tuc::nw::CMessageServer *>,boost::arg<1>>>> 1> ] 1> G:\Quellcode\nc-programming\nc-libs\nc-libs/network/MessageChannel.h(117): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void tuc::nw::CMessageChannel::startAsyncReadImpl<boost::_bi::protected_bind_t<boost::_bi::bind_t<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>>>>(boost::_bi::protected_bind_t<boost::_bi::bind_t<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>>> &&)". 1> with 1> [ 1> T=tuc::nw::CMessageServer * 1> ] 1> G:\Quellcode\nc-programming\nc-libs\nc-libs/network/MessageChannel.h(76): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void tuc::nw::CMessageChannel::startAsyncRead<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>>(boost::_bi::bind_t<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>>)". 1> with 1> [ 1> T=tuc::nw::CMessageServer * 1> ] 1> MessageServer.cpp(43): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void tuc::nw::CMessageChannel::startProcessing<boost::_bi::bind_t<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>>>(boost::_bi::bind_t<void,boost::_mfi::mf1<void,tuc::nw::CMessageServer,tuc::nw::Packet &>,boost::_bi::list2<boost::_bi::value<T>,boost::arg<1>>> &&,bool)". 1> with 1> [ 1> T=tuc::nw::CMessageServer * 1> ] ========== Erstellen: 0 erfolgreich, 1 fehlerhaft, 0 aktuell, 0 übersprungen ==========

This is how you pass Packet instance (as a temporary, i.e. rvalue):
handler(Packet(m_headerInBuffer.getShort(4), bytes_transferred, m_currReadBuffer));
And this is the signature of the function that expects Packet &, i.e. lvalue:
void testPacket(Packet& packet) {}
It seems that they do not match.
participants (2)
-
Igor R
-
Marco