首页 文章

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

提问于
浏览
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 = 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 [含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 [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))'''type'iodata ')输入'const boost :: system :: | \ boost \ bind \ mem_fn_template.hpp | 291 |注意:模板R boost :: _ mfi :: mf2 :: operator()(const U&,A1,A2)const [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))'''type'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&'|没有已知的转换

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

2 回答

  • 3

    使用实例方法时,必须将 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);
    
  • 4

    初始示例失败,因为将调用成员函数的对象实例未传递给 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]支持成员具有多个参数的函数指针,返回的函数对象可以将指针,引用或指向对象实例的智能指针作为其第一个参数 .

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

    • bind调用中的第二个参数必须是对象实例的句柄,因为它将是传递给 boost::mem_fn 返回的函数对象的第一个参数 .

    • 必须在与 _1 占位符匹配的参数位置传递从 boost::bind 返回的函数对象 .

    例如,给定

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

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

相关问题