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 ==========