boost::asio::async_read_until 具有自定义匹配条件运算符重载混淆

boost::asio::async_read_until with custom match condition operator overload confusion

本文关键字:条件运算符 重载 自定义 async asio read until boost      更新时间:2023-10-16

我正在尝试使用自定义匹配函数作为boost::asio组合操作的一部分。 VS2017 在将std::move(*this)作为异步操作的处理程序传入时,无法推断具有自定义匹配条件的参数。

组合操作是一个类,该类具有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));
}
}
}

使用直道时 void handler(boost::system::error_code ec, std::size_t bytes(; 而不是 std::move(*this( 编译得很好。 以下是 MSVC 2017 的输出。 任何能够告诉编译器使用哪个重载的帮助将不胜感激。

1>C:Usersxxxxbuildsdevsrccomm/read_msg.hpp(310): error C2665: 'boost::asio::read_until': none of the 5 overloads could convert all the argument types
1>C:Usersxxxxbuildsboost_1_64_0boost/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:Usersxxxxbuildsboost_1_64_0boost/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:Usersxxxxbuildsboost_1_64_0boost/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:Usersxxxxbuildsboost_1_64_0boost/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:Usersxxxxbuildsboost_1_64_0boost/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:Usersxxxxbuildsdevsrccomm/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:Usersxxxxbuildsdevsrccomm/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:Usersxxxxbuildsdevsrccomm/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:Usersxxxxbuildsdevsrccomm/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:Usersxxxxbuildsdevsrccommtestread_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>        ]

我不确定你想用std::move(*this)实现什么,但即使它是一个写得很好的处理程序,但事实并非如此,从 asio 的手下删除处理程序也不是一个好主意。

在不知道最终目标的情况下,我会用这样的事情来补救这种情况

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<>的生命周期,那么您需要使用不同的方法,我建议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);
});

脚注:有关如何使用 shared_ptr 确保 asio 操作生存期的其他信息,请查看为异步发送缓冲区保留内存(提升 asio 套接字(