2

我正在使用 boost::bind 将处理函数传递给 boost::asio::async_write。当我使用自由函数时,它可以正常工作,但是当我尝试在类中移动函数时,bind 会产生我无法破译的错误。

什么有效:

我写了一些数据:

boost::asio::async_write(*socket,
                         boost::asio::buffer(data(),
                                             length()),
                         boost::bind(handlermessagewrite,
                                     boost::asio::placeholders::error,
                                     this,
                                     boost::asio::placeholders::bytes_transferred));

然后我用一个自由函数处理写入,其签名是:

void handlermessagewrite(const boost::system::error_code& errorcode,
                         iodata *msg,
                         size_t bytes_transferred);

这一切都按预期工作。

我正在尝试做的事情:

我在一个类中移动处理程序ioclient

class ioclient {
public:
  void handlermessagewrite(const boost::system::error_code& errorcode,
                           iodata *msg,
                           size_t bytes_transferred);
}

void ioclient::handlermessagewrite(const boost::system::error_code& errorcode,
                                   iodata *msg,
                                   size_t bytes_transferred);

并相应地调整 boost::bind 代码,如官方 asio 教程中所示:

- boost::bind(handlermessagewrite,

+ boost::bind(&ioclient::handlermessagewrite,

但是,这会产生一些极其不透明的编译错误,而其中一行似乎最终在我的 IDE 中被截断(code::blocks)这一事实无济于事:

\boost\bind\bind_template.hpp|102| 'boost::_bi::bind_t::result_type boost::_bi::bind_t::operator()(const A1&, const A2&) [with A1 = boost::system::error_code; A2 = 无符号整数;R = 无效;F = 升压::_mfi::mf2; L = boost::_bi::list3 (*)(), boost::_bi::value, boost::arg<2> (*)()>; boost::_bi::bind_t::result_type = void]'| \boost\asio\impl\write.hpp|261| 'void boost::asio::detail::write_op::operator()(const boost::system::error_code&, std::size_t, int) [with AsyncWriteStream = boost::asio::basic_stream_socket; CompletionCondition = boost::asio::detail::transfer_all_t; WriteHandler = boost::_bi::bind_t, boost::_bi::list3 (*)(), boost::_bi::va| \boost\asio\impl\write.hpp|585| 'void boost::asio::async_write(AsyncWriteStream&, const ConstBufferSequence&, WriteHandler&&) [with AsyncWriteStream = boost::asio::basic_stream_socket; ConstBufferSequence = boost::asio::mutable_buffers_1; WriteHandler = boost::_bi::bind_t, boost::_bi::list3 (*)(), boost::_bi::value, boost::arg<2> (*)()> >]'| \iodata.cpp|76| 从这里需要| \boost\bind\bind.hpp|392|错误:不匹配调用 '(boost::_mfi::mf2) (const boost::system::error_code&, iodata*&, const unsigned int&)'| \boost\bind\mem_fn_template.hpp|253|注意:候选人是:| \boost\bind\mem_fn_template.hpp|278|注意:R boost::_mfi::mf2::operator()(T*, A1, A2) const [with R = void; T = ioclient; A1 = const boost::system::error_code&; A2 = iodata*]| \boost\bind\mem_fn_template.hpp|278|注意:没有已知的参数 1 从 'const boost::system::error_code' 到 'ioclient*' 的转换 | \boost\bind\mem_fn_template.hpp|283|注意:模板 R boost::_mfi::mf2::operator()(U&, A1, A2) const [with U = U; R = 无效;T = ioclient; A1 = const boost::system::error_code&; A2 = iodata*]| \boost\bind\mem_fn_template.hpp|283|注意:模板参数推导/替换失败:| \boost\bind\bind.hpp|392|注意:不能转换 '(& a)->boost::_bi::list2::operator[]((* &((boost::_bi::list3 (*) (), boost::_bi::value, boost::arg<2> ()()> )this)->boost::_bi::list3 (*)(), boost::_bi::value, boost::arg<2> (*)()>::.boost::_bi ::storage3 (*)(), boost::_bi::value, boost::arg<2> (*)()>::.boost::_bi::storage2 (*)(), boost:: bi ::value >::a2 ))' (输入 'iodata*') 到输入 'const boost::system::| \boost\bind\mem_fn_template.hpp|291|注意:模板 R boost::_mfi::mf2::operator()(const U&, A1, A2) const [with U = U; R = 无效;T = ioclient; A1 = const boost::system::error_code&; A2 = iodata*]| \boost\bind\mem_fn_template.hpp|291|注意:模板参数推导/替换失败:| \boost\bind\bind.hpp|392|注意:不能转换 '(& a)->boost::_bi::list2::operator[]((* &((boost::_bi::list3 (*) (), boost::_bi::value, boost::arg<2> ( )()>)this)->boost::_bi::list3 (*)(), boost::_bi::value, boost::arg<2> (*)()>::.boost::_bi::storage3 ( *)(), boost::_bi::value, boost::arg<2> (*)()>::.boost::_bi::storage2 (*)(), boost:: bi::value > ::a2 ))' (输入 'iodata*') 到输入 'const boost::system::| \boost\bind\mem_fn_template.hpp|299|注意:R boost::_mfi::mf2::operator()(T&, A1, A2) const [with R = void; T = ioclient; A1 = const boost::system::error_code&; A2 = iodata*]| \boost\bind\mem_fn_template.hpp|299|注意:没有已知的参数 1 从 'const boost::system::error_code' 到 'ioclient&' 的转换|

我确信我在绑定方面做错了什么,但我不知道那可能是什么。有任何想法吗?

4

2 回答 2

4

使用实例方法时,必须将this指针作为第二个参数传递给 bind()。

编辑:

我已经完成了您对 boost::asio 所做的尝试。这是我的实现的一个片段:

        boost::asio::async_write(
            m_Socket,
            boost::asio::buffer((const unsigned char *)(rMsg.c_str()), rMsg.length()),
            boost::bind(&ServerToClientConnT::HandleAsioWrite,
                        this,
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred));

其中 HandleAsioWrite 是声明如下的方法:

void HandleAsioWrite(const boost::system::error_code& rErrorCode,
                     std::size_t nBytesTransferred);
于 2012-12-08T04:56:53.110 回答
3

初始示例失败,因为将在其上调用成员函数的对象实例未传递给bind. 这在编译器错误中指出,它指出没有从const boost::system::error_code到的已知转换ioclient*

当使用带有成员指针的Boost.Bind时,据记载

boost::bind(&X::f, args)相当于boost::bind<R>(boost::mem_fn(&X::f), args)

此外,Boost.mem_fn的文档指出:

它[ boost::mem_fn] 支持具有多个参数的成员函数指针,并且返回的函数对象可以将指向对象实例的指针、引用或智能指针作为其第一个参数

因此,如果 的第一个参数boost::bind是成员指针,那么:

  • 绑定调用中的第二个参数必须是对象实例的句柄,因为它将是传递给从返回的函数对象的第一个参数boost::mem_fn
  • 从返回的函数对象boost::bind必须在与_1占位符匹配的参数位置传递对象实例句柄。

例如,给定

struct Foo
{
  void do_something(int x) {}
};

可以使用以下do_something任何一种方式绑定和调用成员函数:

Foo f;
boost::bind(&Foo::do_something, &f, _1)(42);     // handle is second argument.
boost::bind(&Foo::do_something, _1, _2)(&f, 42); // handle matches _1 position.
boost::bind(&Foo::do_something, _2, _1)(42, &f); // handle matches _1 position.

使用 Boost.Asio,boost::asio::placeholders::error实现为占位符_1。出于这个原因,对象实例必须bind作为第二个参数传递给调用,或者对象实例必须作为参数传递给自由函数或静态成员函数,然后将调用对象实例上的成员函数。 是一个使用非静态成员函数编译的解决方案示例,但感兴趣的片段是:

ioclient client;
iodata data;

boost::asio::async_write(
  socket,
  boost::asio::null_buffers(),
  boost::bind(&ioclient::handlermessagewrite,
              &client,
              boost::asio::placeholders::error,
              &data,
              boost::asio::placeholders::bytes_transferred));

在对Lou的响应中发布的编译器错误表明成员函数正在尝试使用不兼容类型的实例句柄来调用。要成为兼容类型,它必须继承自. 如果这是预期的类型层次结构,则验证继承是否正确。否则,请仔细将参数类型和位置与被绑定的函数匹配。ioclientiodataiodataioclient

于 2012-12-10T15:33:58.160 回答