boost :: bind与成员函数(作为boost :: asio异步写入处理程序)

时间:2012-12-08 04:35:34

标签: c++ boost asynchronous boost-asio boost-bind

我正在使用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)中被截断的事实没有帮助:

  

\升压\绑定\ 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 = unsigned int; R =无效; F = boost :: _ mfi :: mf2; L = boost :: _ bi :: list3(*)(),boost :: _ bi :: value,boost :: arg< 2> (*)()取代; boost :: _ bi :: bind_t :: result_type = void]'|   \提升\ 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 |   \提升\ 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&amp ;; 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 [U = U; R =无效; T = ioclient; A1 = const boost :: system :: error_code&amp ;; 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&amp ;; 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&amp ;; A2 = iodata *] |   \ boost \ bind \ mem_fn_template.hpp | 299 |注意:参数1从'const boost :: system :: error_code'到'ioclient&'|

没有已知的转换

我确信我在使用bind做错了,但是我对这可能是什么感到茫然。有什么想法吗?

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:3)

初始示例失败,因为将调用成员函数的对象实例不会传递给bind。这在编译器错误中表示,它指出没有从const boost::system::error_codeioclient*的已知转换。

Boost.Bind与成员指针一起使用时,记录为

  

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

此外,Boost.mem_fn的文档说明:

  

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

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

  • 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调用,或者必须将对象实例作为参数传递给自由函数或静态成员函数,然后调用成员函数在对象实例上。 Here是使用非静态成员函数编译的解决方案示例,但感兴趣的片段是:

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));

compiler error响应中发布的Lou表示正在尝试使用ioclient的实例句柄调用iodata成员函数,这是一种不兼容的类型。要使iodata成为兼容类型,必须从ioclient继承。如果这是预期的类型层次结构,则验证继承是否正确。否则,请仔细匹配参数类型和位置与绑定的函数。