简体   繁体   English

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

[英]boost::bind with member functions (as boost::asio async write handler)

I'm using boost::bind to pass a handler function to boost::asio::async_write. 我正在使用boost :: bind传递处理程序函数来boost :: asio :: async_write。 When I use free functions, it works fine, but when I try to move the functions inside a class, bind produces errors that I am unable to decipher. 当我使用自由函数时,它可以正常工作,但是当我尝试在一个类中移动函数时,bind会产生我无法解读的错误。

What works: 什么有效:

I write some data with: 我写了一些数据:

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

Then I handle the write with a free function whose signature is: 然后我使用自由函数处理写入,其签名是:

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

This all works as expected. 这一切都按预期工作。

What I'm trying to do: 我正在尝试做什么:

I'm moving the handler inside a class ioclient : 我正在一个类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);

and adapting the boost::bind code accordingly, as seen in the official asio tutorials: 并相应地修改boost :: bind代码,如官方的asio教程所示:

- boost::bind(handlermessagewrite,

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

However, this produces some extremely opaque compile errors, not helped by the fact that one of the lines seems to end up truncated in my IDE (code::blocks): 但是,这会产生一些非常不透明的编译错误,而其中的一行似乎最终在我的IDE中被截断了(代码:: blocks),这无济于事:

\\boost\\bind\\bind_template.hpp|102| \\提升\\绑定\\ bind_template.hpp | 102 | required from 'boost::_bi::bind_t::result_type boost::_bi::bind_t::operator()(const A1&, const A2&) [with A1 = boost::system::error_code; 需要从'boost :: _ bi :: bind_t :: result_type boost :: _ bi :: bind_t :: operator()(const A1&,const A2&)[with A1 = boost :: system :: error_code; A2 = unsigned int; A2 = unsigned int; R = void; R =无效; F = boost::_mfi::mf2; F = boost :: _ mfi :: mf2; L = boost::_bi::list3 (*)(), boost::_bi::value, boost::arg<2> (*)()>; L = boost :: _ bi :: list3(*)(),boost :: _ bi :: value,boost :: arg <2>(*)()>; boost::_bi::bind_t::result_type = void]'| boost :: _ bi :: bind_t :: result_type = void]'| \\boost\\asio\\impl\\write.hpp|261| \\提升\\ ASIO \\ IMPL \\ write.hpp | 261 | required from 'void boost::asio::detail::write_op::operator()(const boost::system::error_code&, std::size_t, int) [with AsyncWriteStream = boost::asio::basic_stream_socket; 需要从'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; CompletionCondition = boost :: asio :: detail :: transfer_all_t; WriteHandler = boost::_bi::bind_t, boost::_bi::list3 (*)(), boost::_bi::va| WriteHandler = boost :: _ bi :: bind_t,boost :: _ bi :: list3(*)(),boost :: _ bi :: va | \\boost\\asio\\impl\\write.hpp|585| \\提升\\ ASIO \\ IMPL \\ write.hpp | 585 | required from 'void boost::asio::async_write(AsyncWriteStream&, const ConstBufferSequence&, WriteHandler&&) [with AsyncWriteStream = boost::asio::basic_stream_socket; 需要从'void boost :: asio :: async_write(AsyncWriteStream&,const ConstBufferSequence&,WriteHandler &&)[with AsyncWriteStream = boost :: asio :: basic_stream_socket; ConstBufferSequence = boost::asio::mutable_buffers_1; ConstBufferSequence = boost :: asio :: mutable_buffers_1; WriteHandler = boost::_bi::bind_t, boost::_bi::list3 (*)(), boost::_bi::value, boost::arg<2> (*)()> >]'| WriteHandler = boost :: _ bi :: bind_t,boost :: _ bi :: list3(*)(),boost :: _ bi :: value,boost :: arg <2>(*)()>>]'| \\iodata.cpp|76| \\ iodata.cpp | 76 | required from here| 从这里要求| \\boost\\bind\\bind.hpp|392|error: no match for call to '(boost::_mfi::mf2) (const boost::system::error_code&, iodata*&, const unsigned int&)'| \\ boost \\ bind \\ bind.hpp | 392 |错误:没有匹配调用'(boost :: _ mfi :: mf2)(const boost :: system :: error_code&,iodata *&,const unsigned int&)'| \\boost\\bind\\mem_fn_template.hpp|253|note: candidates are:| \\\\ boost \\ bind \\ mem_fn_template.hpp | 253 |注意:候选人为:| \\boost\\bind\\mem_fn_template.hpp|278|note: R boost::_mfi::mf2::operator()(T*, A1, A2) const [with R = void; \\ boost \\ bind \\ mem_fn_template.hpp | 278 |注意:R boost :: _ mfi :: mf2 :: operator()(T *,A1,A2)const [with R = void; T = ioclient; T = ioclient; A1 = const boost::system::error_code&; A1 = const boost :: system :: error_code&; A2 = iodata*]| A2 = iodata *] | \\boost\\bind\\mem_fn_template.hpp|278|note: no known conversion for argument 1 from 'const boost::system::error_code' to 'ioclient*'| \\ boost \\ bind \\ mem_fn_template.hpp | 278 |注意:参数1从'const boost :: system :: error_code'到'ioclient *'|的转换未知 \\boost\\bind\\mem_fn_template.hpp|283|note: template R boost::_mfi::mf2::operator()(U&, A1, A2) const [with U = U; \\\\ boost \\ bind \\ mem_fn_template.hpp | 283 |注意:模板R boost :: _ mfi :: mf2 :: operator()(U&,A1,A2)const [with U = U; R = void; R =无效; T = ioclient; T = ioclient; A1 = const boost::system::error_code&; A1 = const boost :: system :: error_code&; A2 = iodata*]| A2 = iodata *] | \\boost\\bind\\mem_fn_template.hpp|283|note: template argument deduction/substitution failed:| \\ boost \\ bind \\ mem_fn_template.hpp | 283 |注意:模板参数推导/替换失败:| \\boost\\bind\\bind.hpp|392|note: cannot convert '(& 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*') to type 'const boost::system::| \\ 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|note: template R boost::_mfi::mf2::operator()(const U&, A1, A2) const [with U = U; \\\\ boost \\ bind \\ mem_fn_template.hpp | 291 |注意:模板R boost :: _ mfi :: mf2 :: operator()(const U&,A1,A2)const [with U = U; R = void; R =无效; T = ioclient; T = ioclient; A1 = const boost::system::error_code&; A1 = const boost :: system :: error_code&; A2 = iodata*]| A2 = iodata *] | \\boost\\bind\\mem_fn_template.hpp|291|note: template argument deduction/substitution failed:| \\ boost \\ bind \\ mem_fn_template.hpp | 291 |注意:模板参数推导/替换失败:| \\boost\\bind\\bind.hpp|392|note: cannot convert '(& 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*') to type 'const boost::system::| \\ 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|note: R boost::_mfi::mf2::operator()(T&, A1, A2) const [with R = void; \\ boost \\ bind \\ mem_fn_template.hpp | 299 |注意:R boost :: _ mfi :: mf2 :: operator()(T&,A1,A2)const [with R = void; T = ioclient; T = ioclient; A1 = const boost::system::error_code&; A1 = const boost :: system :: error_code&; A2 = iodata*]| A2 = iodata *] | \\boost\\bind\\mem_fn_template.hpp|299|note: no known conversion for argument 1 from 'const boost::system::error_code' to 'ioclient&'| \\ boost \\ bind \\ mem_fn_template.hpp | 299 |注意:参数1从'const boost :: system :: error_code'到'ioclient&'|没有已知的转换

I'm convinced I'm doing something wrong with bind, but I'm at a loss as to what that may be. 我确信我在使用bind时出错了,但是我可能会茫然。 Any ideas? 有任何想法吗?

When using a instance method, you must pass the this pointer as the second argument to bind(). 使用实例方法时,必须将this指针作为第二个参数传递给bind()。

EDIT: 编辑:

I've done what you are trying to do with boost::asio. 我已经完成了你想用boost :: asio做的事情。 Here is a snippet from my implementation: 这是我实现的一个片段:

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

where HandleAsioWrite is method declared as follows: 其中HandleAsioWrite的方法声明如下:

void HandleAsioWrite(const boost::system::error_code& rErrorCode,
                     std::size_t nBytesTransferred);

The initial example is failing because the object instance on which the member-function will be invoked is not passed to bind . 最初的示例是失败的,因为将调用成员函数的对象实例不会传递给bind This is indicated in the compiler error where it states that there is no known conversion from const boost::system::error_code to ioclient* . 编译器错误表明了这一点,该错误指出没有已知的从const boost::system::error_codeioclient*

When using Boost.Bind with member pointers, it is documented that 当使用Boost.Bind和成员指针时,会记录下来

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

Furthermore, Boost.mem_fn 's documentation states: 此外, Boost.mem_fn的文档说明:

It [ boost::mem_fn ] supports member function pointers with more than one argument, and the returned function object can take a pointer, a reference, or a smart pointer to an object instance as its first argument . 它[ boost::mem_fn ]支持具有多个参数的成员函数指针,并且返回的函数对象可以将指向对象实例的指针,引用或智能指针作为其第一个参数

Thus, if this first argument of boost::bind is a member-pointer, then either: 因此,如果boost::bind第一个参数是成员指针,则可以:

  • The second argument in the bind call must be a handle to the object instance, as it will be the first argument passed to the function object returned from boost::mem_fn . bind调用中的第二个参数必须是对象实例的句柄,因为它将是传递给boost::mem_fn返回的函数对象的第一个参数。
  • The function object returned from boost::bind must be passed the object instance handle in the argument position matching the _1 placeholder. boost::bind返回的函数对象必须在与_1占位符匹配的参数位置传递对象实例句柄。

For example, given 例如,给定

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

The do_something member function could be bound and invoked with any of the following: 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.

With Boost.Asio, boost::asio::placeholders::error is implemented as placeholder _1 . 使用Boost.Asio, boost::asio::placeholders::error实现为占位符_1 For this reason, the object instance must be passed to the bind call as the second argument, or the object instance must be passed as an argument to either a free function or static member function, that will then invoke the member function on the object instance. 因此,必须将对象实例作为第二个参数传递给bind调用,或者必须将对象实例作为自由函数或静态成员函数的参数传递,然后将在对象实例上调用成员函数。 Here is an example of solution that compiles with a non-static member function, but the snippet of interests is: 以下是使用非静态成员函数编译的解决方案示例,但感兴趣的片段是:

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

The compiler error posted in the response to Lou indicates that an ioclient member function is attempting to be invoked with an instance handle of iodata , an incompatible type. 在对Lou的响应中发布的编译器错误表示正在尝试使用不兼容类型的iodata的实例句柄调用ioclient成员函数。 For iodata to be a compatible type, it must be inherited from ioclient . 为了使iodata成为兼容类型,必须从ioclient继承ioclient If this is the intended type hierarchy, then verify that inheritance is correct. 如果这是预期的类型层次结构,请验证继承是否正确。 Otherwise, carefully match the argument types and positions with the function being bound. 否则,请将参数类型和位置与绑定的函数仔细匹配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM