2017-08-13 8 views
1

私は、boost :: asio合成操作の一部としてカスタムマッチ関数を使用しようとしています。非同期操作のハンドラとしてstd::move(*this)を渡すとき、VS2017はカスタム一致条件でパラメータを推論できません。boost :: asio :: async_read_until withカスタム一致条件演算子オーバーロードの混乱

複合操作は、 void operator()(boost::beast::error_code ec, std::size_t bytes_transferred)オーバーロードを持つクラスです。例えば:

class match_char 
{ 
public: 
    explicit match_char(char c) : c_(c) {} 

    template <typename Iterator> 
    std::pair<Iterator, bool> operator()(
     Iterator begin, Iterator end) const 
    { 
    Iterator i = begin; 
    while (i != end) 
     if (c_ == *i++) 
     return std::make_pair(i, true); 
    return std::make_pair(i, false); 
    } 

private: 
    char c_; 
}; 

namespace asio { 
    template <> struct is_match_condition<match_char> 
    : public boost::true_type {}; 
} // namespace asio 

template<class AsyncStream, class DynamicBuffer, class Handler> 
class composed_op 
{ 
public: 
int state = 0; 
// --- boilerplate code 
void operator()(boost::beast::error_code ec, std::size_t bytes_transferred) 
{ 
    switch(state) 
    { 
      case x: 
       return boost::asio::async_read_until(stream, buffer, match_char('a'), std::move(*this)); 
    } 
} 

} 

ストレート 無効ハンドラを使用して(後押し::システム:: ERROR_CODE EC、STDを:: size_tのバイト); std :: move(* this)の代わりに がうまくコンパイルされます。以下はMSVC 2017の出力です。どのオーバーロードを使用するかをコンパイラに伝えることができれば、大いに感謝します。

1>C:\Users\xxxx\builds\dev\src\comm/read_msg.hpp(310): error C2665: 'boost::asio::read_until': none of the 5 overloads could convert all the argument types 
1>C:\Users\xxxx\builds\boost_1_64_0\boost/asio/impl/read_until.hpp(265): note: could be 'size_t boost::asio::read_until<AsyncStream,std::allocator<char>,comm::detail::match_char>(SyncReadStream &,boost::asio::basic_streambuf<std::allocator<char>> &,MatchCondition,boost::system::error_code &,void *)' 
1>  with 
1>  [ 
1>   AsyncStream=boost::beast::test::string_iostream, 
1>   SyncReadStream=boost::beast::test::string_iostream, 
1>   MatchCondition=comm::detail::match_char 
1>  ] 
1>C:\Users\xxxx\builds\boost_1_64_0\boost/asio/impl/read_until.hpp(317): note: or  'size_t boost::asio::read_until<AsyncStream,std::allocator<char>,comm::detail::match_char>(SyncReadStream &,boost::asio::basic_streambuf<std::allocator<char>> &,MatchCondition,void *)' 
1>  with 
1>  [ 
1>   AsyncStream=boost::beast::test::string_iostream, 
1>   SyncReadStream=boost::beast::test::string_iostream, 
1>   MatchCondition=comm::detail::match_char 
1>  ] 
1>C:\Users\xxxx\builds\boost_1_64_0\boost/asio/impl/read_until.hpp(206): note: or  'size_t boost::asio::read_until<AsyncStream,std::allocator<char>>(SyncReadStream &,boost::asio::basic_streambuf<std::allocator<char>> &,const boost::regex &,boost::system::error_code &)' 
1>  with 
1>  [ 
1>   AsyncStream=boost::beast::test::string_iostream, 
1>   SyncReadStream=boost::beast::test::string_iostream 
1>  ] 
1>C:\Users\xxxx\builds\boost_1_64_0\boost/asio/impl/read_until.hpp(139): note: or  'size_t boost::asio::read_until<AsyncStream,std::allocator<char>>(SyncReadStream &,boost::asio::basic_streambuf<std::allocator<char>> &,const std::string &,boost::system::error_code &)' 
1>  with 
1>  [ 
1>   AsyncStream=boost::beast::test::string_iostream, 
1>   SyncReadStream=boost::beast::test::string_iostream 
1>  ] 
1>C:\Users\xxxx\builds\boost_1_64_0\boost/asio/impl/read_until.hpp(48): note: or  'size_t boost::asio::read_until<AsyncStream,std::allocator<char>>(SyncReadStream &,boost::asio::basic_streambuf<std::allocator<char>> &,char,boost::system::error_code &)' 
1>  with 
1>  [ 
1>   AsyncStream=boost::beast::test::string_iostream, 
1>   SyncReadStream=boost::beast::test::string_iostream 
1>  ] 
1>C:\Users\xxxx\builds\dev\src\comm/read_msg.hpp(310): note: while trying to match the argument list '(boost::beast::test::string_iostream, boost::asio::streambuf, comm::detail::match_char, comm::read_msg_op<AsyncStream,DynamicBuffer,____C_A_T_C_H____T_E_S_T____74::<lambda_881e0622dc11cafb22751f624439b95e>>)' 
1>  with 
1>  [ 
1>   AsyncStream=boost::beast::test::string_iostream, 
1>   DynamicBuffer=comm::wire_msg 
1>  ] 
1>C:\Users\xxxx\builds\dev\src\comm/read_msg.hpp(286): note: while compiling class template member function 'void comm::read_msg_op<AsyncStream,DynamicBuffer,____C_A_T_C_H____T_E_S_T____74::<lambda_881e0622dc11cafb22751f624439b95e>>::operator()(boost::beast::error_code,::size_t)' 
1>  with 
1>  [ 
1>   AsyncStream=boost::beast::test::string_iostream, 
1>   DynamicBuffer=comm::wire_msg 
1>  ] 
1>C:\Users\xxxx\builds\dev\src\comm/read_msg.hpp(483): note: see reference to function template instantiation 'void comm::read_msg_op<AsyncStream,DynamicBuffer,____C_A_T_C_H____T_E_S_T____74::<lambda_881e0622dc11cafb22751f624439b95e>>::operator()(boost::beast::error_code,::size_t)' being compiled 
1>  with 
1>  [ 
1>   AsyncStream=boost::beast::test::string_iostream, 
1>   DynamicBuffer=comm::wire_msg 
1>  ] 
1>C:\Users\xxxx\builds\dev\src\comm/read_msg.hpp(483): note: see reference to class template instantiation 'comm::read_msg_op<AsyncStream,DynamicBuffer,____C_A_T_C_H____T_E_S_T____74::<lambda_881e0622dc11cafb22751f624439b95e>>' being compiled 
1>  with 
1>  [ 
1>   AsyncStream=boost::beast::test::string_iostream, 
1>   DynamicBuffer=comm::wire_msg 
1>  ] 
1>C:\Users\xxxx\builds\dev\src\comm\test\read_msg_test.cpp(55): note: see reference to function template instantiation 'void comm::read_msg<boost::beast::test::string_iostream,comm::wire_msg,____C_A_T_C_H____T_E_S_T____74::<lambda_881e0622dc11cafb22751f624439b95e>&>(AsyncStream &,DynamicBuffer &,CompletionToken)' being compiled 
1>  with 
1>  [ 
1>   AsyncStream=boost::beast::test::string_iostream, 
1>   DynamicBuffer=comm::wire_msg, 
1>   CompletionToken=____C_A_T_C_H____T_E_S_T____74::<lambda_881e0622dc11cafb22751f624439b95e> & 
1>  ] 

答えて

3

私はあなたがstd::move(*this)で達成しようとしているのかわからないのですが、それはそれはないですよく書かれたハンドラであったとしても、ASIOの手の下からハンドラを削除するには良いアイデアではありません。

最終目標を知らなくても、あなたの懸念がcomposed_op<>の寿命があるならば、私は、あなたは別のアプローチを使用する必要があり、この

return boost::asio::async_read_until(
    stream, buffer, match_char('a'), 
    [this](const boost::system::error_code& ec, size_t bytes_transferred) { 
     // handler code comes here 
     // is the following what you are trying to achieve? 
     this->operator()(ec, bytes_transferred); 
    }); 

ようなもので状況を改善だろうと私は継承するcomposed_opをお勧めしますstd :: enable_shared_from_this <>このようなハンドラの書き換え:

return boost::asio::async_read_until(
    stream, buffer, match_char('a'), 
    [self = shared_from_this()] 
    (const boost::system::error_code& ec, size_t bytes_transferred) { 
     // handler code comes here 
     // is the following what you are trying to achieve? 
     self->operator()(ec, bytes_transferred); 
    }); 

脚注:ASIO操作で寿命を確保するためのshared_ptrを使用する方法の追加情報については、CHECをk out Reserving memory for asynchronous send buffers (boost asio sockets)