提升async_read_until自定义匹配功能的问题在 GCC 中不符合

boost async_read_until problem with custom match function won't complile in GCC

本文关键字:问题 不符合 功能 GCC read async until 自定义 提升      更新时间:2023-10-16

下面的代码可以在visual studio 2010下编译和工作,但在GCC下无法编译:

声明:

boost::asio::strand m_strand; typedef boost::asio::buffers_iterator< boost::asio::streambuf::const_buffers_type > iterator; std::pair<iterator, bool> match_version(iterator begin, iterator end);

实施

:

std::pair<TcpMimeConnection::iterator, bool> TcpMimeConnection::match_version(iterator begin, iterator end)
{
    boost::match_results<iterator> matchResult;
    const bool found = boost::regex_search( begin, end, matchResult, boost::regex("MIME-Version:\s*1.0\s*rn", boost::regex::icase));
    if(found)
    {
        versionFound = true;
        return std::make_pair(matchResult[0].second, true);
    }
    else if (std::distance(begin,end) >= MAX_STREAM_READ_SIZE)
    {
        return std::make_pair(end, true);
    }
    return std::make_pair(begin, false);
}
/**
 * Start an async read to of a mime message.
 * @return the operation ID for this operation.
 */
sapphire::OperationId TcpMimeConnection::read()
{
    const sapphire::OperationId id = getNextOperationId();
    versionFound = false;
    aio::async_read_until(
            socket(),
            buffer(),
            boost::bind(&TcpMimeConnection::match_version, shared_from_this(), _1, _2),
            m_strand.wrap(
                    boost::bind(
                            &TcpMimeConnection::handleMimeVersion,
                            shared_from_this(),
                            id,
                            aio::placeholders::error,
                            aio::placeholders::bytes_transferred)));
    return id;
}

我得到以下错误:

[11:20:59]: TcpMimeConnection.cpp:372: instantiated from here[11:20:59]: read_til .hpp:60:错误:调用重载的' helper(const boost::_bi::bind_t, bool>, boost::_mfi::mf2, bool>, sapphire::transport::ip::TcpMimeConnection, boost::asio::buffers_iterator, boost::asio::buffers_iterator>, boost::_bi::list3>, boost::arg<1>, boost::arg<2>>>&) '是不明确的[11:20:59]: read_until.hpp:57:注:候选人是:boost:: asio::::静态has_result_type::大提高::asio:::: has_result_type:辅助(U,…)[U =提高::_bi:: bind_t, bool>, boost:: _mfi:: mf2, bool>,蓝宝石::交通::ip:: TcpMimeConnection, boost:: asio:: buffers_iterator, boost:: asio:: buffers_iterator>, boost:: _bi:: list3>, boost:: arg<1>, boost:: arg<2>>>, T = boost:: _bi:: bind_t, bool>, boost:: _mfi:: mf2, bool>,蓝宝石::交通::ip:: TcpMimeConnection, boost:: asio:: buffers_iterator, boost:: asio:: buffers_iterator>,boost:: _bi: list3>, boost:: arg<1>, boost:: arg<2>>>)[11:20:59]: read_till .hpp:58;静态字符增加:asio:::: has_result_type:辅助(U, typename U:: result_type *) [U =提高::_bi:: bind_t, bool>, boost:: _mfi:: mf2, bool>,蓝宝石::交通::ip:: TcpMimeConnection, boost:: asio:: buffers_iterator, boost:: asio:: buffers_iterator>, boost:: _bi:: list3>, boost:: arg<1>, boost:: arg<2>>>, T = boost:: _bi:: bind_t, bool>, boost:: _mfi:: mf2, bool>,蓝宝石::交通::ip:: TcpMimeConnection, boost:: asio:: buffers_iterator, boost:: asio:: buffers_iterator>,boost:: _bi: list3>, boost:: arg<1>, boost:: arg<2>>>)[11:20:59]: TcpMimeConnection.cpp: In member function ' virtual sapphire::OperationId sapphire::transport::ip::TcpMimeConnection::read() ':[11:20:59]: sapphire/transport/ip/TcpMimeConnection.cpp:372: error:没有匹配的函数调用"async_read_until (boost:: asio: basic_stream_socket>,, boost:: asio:: basic_streambuf>,, boost:: _bi:: bind_t, bool>, boost:: _mfi:: mf2, bool>,蓝宝石::交通::ip:: TcpMimeConnection, boost:: asio:: buffers_iterator, boost:: asio:: buffers_iterator>, boost:: _bi:: list3>, boost:: arg<1>, boost:: arg<2>>>, boost:: asio:::: wrapped_handler, boost:: _bi:: list4>, boost:: _bi::价值,提升::arg<1> () (), boost:: arg<2> ()()>>>)’

当我简单地传递boost::regex("MIME-Version:s*1.0s*rn", boost::regex::icase)到async_read_until(第三次重载)中没有问题,但是我想自定义async_read_until(第四次重载)的匹配条件,当我使匹配条件成为成员函数时,我遇到了问题。我需要match_version是一个成员函数,因为没有办法通知处理程序为什么返回(大小或匹配找到)。所以我知道问题是boost::bind(&TcpMimeConnection::match_version, shared_from_this(), _1, _2),

看起来,为了使用绑定器作为匹配,您将需要为这种类型专门化boost::asio::is_match_condition,尽管文档声明可以使用任何定义result_type的东西。

在添加了所有必要的东西使你的代码编译(下次,请发布一个可编译的例子),我能够重现你的错误,我能够通过添加以下内容来修复它:

namespace boost {
 namespace asio {
  template <> struct is_match_condition<
            decltype(
               boost::bind(&TcpMimeConnection::match_version,
                         shared_ptr<TcpMimeConnection>(), _1, _2)
                    )>
  : public boost::true_type {};
 }
}

这显然是笨拙的,我将在这里使用命名函数对象而不是绑定器。

这是我根据Cubbi的答案使用的解决方案,它可以在visual studio 2010和gcc 4.4.2下编译:

class MatchVersion {
 public:
  explicit MatchVersion(bool& versionFound) : m_versionFound(versionFound) {}
  typedef boost::asio::buffers_iterator<
      boost::asio::streambuf::const_buffers_type>
      iterator;
  template <typename Iterator>
  std::pair<Iterator, bool> operator()(Iterator begin, Iterator end) const {
    boost::match_results<iterator> matchResult;
    const bool found = boost::regex_search(
        begin, end, matchResult,
        boost::regex("MIME-Version:\s*1.0\s*rn", boost::regex::icase));
    if (found) {
      m_versionFound = true;
      return std::make_pair(matchResult[0].second, true);
    } else if (std::distance(begin, end) >=
               sapphire::transport::ip::TcpMimeConnection::
                   MAX_STREAM_READ_SIZE) {
      return std::make_pair(end, true);
    }
    return std::make_pair(begin, false);
  }
  MatchVersion(const MatchVersion& other)
      : m_versionFound(other.m_versionFound) {}
 private:
  bool& m_versionFound;
  MatchVersion& operator=(const MatchVersion& other);
};
namespace boost::asio {
template <>
struct is_match_condition<MatchVersion> : public boost::true_type {};
}  // namespace boost::asio
namespace sapphire::transport::ip {
sapphire::OperationId TcpMimeConnection::read() {
  const sapphire::OperationId id = getNextOperationId();
  m_versionFound = false;
  aio::async_read_until(
      socket(), buffer(), MatchVersion(m_versionFound),
      m_strand.wrap(boost::bind(
          &TcpMimeConnection::handleMimeVersion, shared_from_this(), id,
          aio::placeholders::error, aio::placeholders::bytes_transferred)));
  return id;
}
}  // namespace sapphire::transport::ip

我看不出有什么明显的东西,但是asio接口非常糟糕。

当我遇到这样的问题时,我开始分解内联代码。鉴于你最后的声明,我猜shared_from_this可能会混淆它。如果你开始明确地说出你认为所有这些内联的东西是什么意思,你可能会发现你错误的假设。
boost::shared_ptr<TcpMimeConnection> temp = shared_from_this();
boost::bind(&TcpMimeConnection::match_version, temp, _1, _2);

boost::bind(&TcpMimeConnection::match_version, this, _1, _2);