Boost logo

Boost Users :

Subject: [Boost-users] problems with nested boost::bind and boost::asio
From: Marco (marco.schumann_at_[hidden])
Date: 2014-04-03 02:34:05


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


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net