2

boost::bind を使用して、ハンドラー関数を boost::asio::async_write に渡します。無料の関数を使用すると問題なく動作しますが、関数をクラス内に移動しようとすると、バインドで解読できないエラーが発生します。

機能するもの:

私はいくつかのデータを書きます:

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

公式の asio チュートリアルに見られるように、それに応じて boost::bind コードを調整します。

- boost::bind(handlermessagewrite,

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

ただし、これにより、いくつかの非常に不透明なコンパイル エラーが発生します。これは、IDE で行の 1 つが切り詰められているように見えるという事実 (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 = 符号なし int; 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|注: 'const boost::system::error_code' から 'ioclient*' への引数 1 の既知の変換はありません | | \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|注: 'const boost::system::error_code' から 'ioclient&' への引数 1 の既知の変換はありません|

私はバインドで何か間違ったことをしていると確信していますが、それが何であるかについて途方に暮れています。何か案は?

4

2 に答える 2

4

インスタンスメソッドを使用する場合は、thisbind()の2番目の引数としてポインタを渡す必要があります。

編集:

私はあなたが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

メンバ関数が呼び出されるオブジェクト インスタンスが に渡されないため、最初の例は失敗しますbindconst 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メンバー ポインターである場合は、次のいずれかになります。

  • bind 呼び出しの 2 番目の引数は、オブジェクト インスタンスへのハンドルである必要があります。これは、 から返される関数オブジェクトに渡される最初の引数になるから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ます。このため、オブジェクト インスタンスをbind2 番目の引数として呼び出しに渡すか、オブジェクト インスタンスを引数としてフリー関数または静的メンバー関数に渡す必要があります。これにより、オブジェクト インスタンスのメンバー関数が呼び出されます。 非静的メンバー関数でコンパイルするソリューションの例を次に示しますが、関心のあるスニペットは次のとおりです

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 に答える