自定义匹配函数的 boost async_read_until 问题在 GCC 中无法编译

发布于 2024-11-26 11:43:52 字数 4223 浏览 3 评论 0原文

以下代码可在 Visual Studio 2010 中编译并使用,但无法在 GCC 下编译:

声明:

升压::asio::strand m_strand; typedef boost::asio::buffers_iterator< boost::asio::streambuf::const_buffers_type >迭代器; std::pair<迭代器,布尔> match_version(迭代器开始,迭代器结束);

实施:

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*\r\n", 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: 从这里实例化 [11:20:59]: read_until.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: 注意:候选者是: static boost::asio::detail::has_result_type::big boost::asio::detail::has_result_type::helper(U, . ..) [U = boost::_bi::bind_t, bool>, boost::_mfi::mf2, bool>,蓝宝石::transport::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>、蓝宝石::transport::ip::TcpMimeConnection、boost::asio::buffers_iterator、boost::asio ::buffers_iterator >、boost::_bi::list3 >、boost::arg<1>、升压::arg<2> > >] [11:20:59]: read_until.hpp:58: 注意:static char boost::asio::detail::has_result_type::helper(U, typename U::result_type*) [with U = boost::_bi: :bind_t, 布尔>, boost::_mfi::mf2, 布尔>,蓝宝石::transport::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>、蓝宝石::transport::ip::TcpMimeConnection、boost::asio::buffers_iterator、boost::asio ::buffers_iterator >、boost::_bi::list3 >、boost::arg<1>、升压::arg<2> > >] [11:20:59]:TcpMimeConnection.cpp:在成员函数“virtual sapphire::OperationId sapphire::transport::ip::TcpMimeConnection::read()”中: [11:20:59]: sapphire/transport/ip/TcpMimeConnection.cpp:372: 错误: 没有匹配的函数用于调用 'async_read_until(boost::asio::basic_stream_socket >&, boost::asio::basic_streambuf >&, boost::_bi::bind_t, bool>, boost::_mfi::mf2、 bool>、 sapphire::transport::ip::TcpMimeConnection、 boost::asio::buffers_iterator、 boost::asio::buffers_iterator >、 boost::_bi::list3 >、升压::arg<1>、升压::arg<2>>、 boost::asio::detail::wrapped_handler、boost::_bi::list4 >、boost::_bi::value、boost::arg<1> ()()、boost::arg<2> ; ()()> >)'

当我简单地通过了boost::regex("MIME-Version:\s*1.0\s*\r\n", boost::regex::icase) 进入 async_read_until (第三次重载)没有问题,但我想自定义匹配async_read_until (第四次重载)的条件,当我将匹配条件设为成员函数时,我遇到了问题。我需要 match_version 成为成员函数,因为无法向处理程序发出信号为什么返回(找到大小或匹配)。所以我知道问题出在 boost::bind(&TcpMimeConnection::match_version, shared_from_this(), _1, _2), 行代码,但我不知道如何修复它。

The following code compiles and works with visual studio 2010 but won't complile under GCC:

Declarations:


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

Implimentation:

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*\r\n", 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;
}

I get the following error:

[11:20:59]: TcpMimeConnection.cpp:372: instantiated from here
[11:20:59]: read_until.hpp:60: error: call of overloaded ‘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> > >&)’ is ambiguous
[11:20:59]: read_until.hpp:57: note: candidates are: static boost::asio::detail::has_result_type::big boost::asio::detail::has_result_type::helper(U, ...) [with U = 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> > >, T = 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:58: note: static char boost::asio::detail::has_result_type::helper(U, typename U::result_type*) [with U = 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> > >, T = 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]: TcpMimeConnection.cpp: In member function ‘virtual sapphire::OperationId sapphire::transport::ip::TcpMimeConnection::read()’:
[11:20:59]: sapphire/transport/ip/TcpMimeConnection.cpp:372: error: no matching function for call to ‘async_read_until(boost::asio::basic_stream_socket >&, boost::asio::basic_streambuf >&, 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> > >, boost::asio::detail::wrapped_handler, boost::_bi::list4 >, boost::_bi::value, boost::arg<1> ()(), boost::arg<2> ()()> > >)’

When I simply passed the boost::regex("MIME-Version:\s*1.0\s*\r\n", boost::regex::icase) into the async_read_until (third overload) there was no problems, but I wanted to customize the match condition of the async_read_until (fourth overload) and I ran into problems when I made the match condition an member function. I need match_version to be a member function since there is no way to signal the handler why its returning (size or match found). So I know the problem is with the boost::bind(&TcpMimeConnection::match_version, shared_from_this(), _1, _2),
line of code but I don't know how to fix it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

渡你暖光 2024-12-03 11:43:52

看来,为了使用活页夹作为匹配,您需要专门针对这种类型的 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 {};
 }
}

这显然很笨拙,我会使用这里是一个命名函数对象而不是绑定器。

It appears that in order to use a binder as a match, you will need to specialize boost::asio::is_match_condition for this type, even though the documentation states that anything that defines a result_type can be used.

After adding all the necessary stuff to make your code compile (next time, please post a compilable example), I was able to reproduce your error, and I was able to fix it by adding the following:

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

This is obviously unwieldy, I would use a named function object here instead of a binder.

岁吢 2024-12-03 11:43:52

这是我根据 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*\r\n", 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

Here is the solution I used based off of Cubbi's answer that compiles under both visual studio 2010 and 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*\r\n", 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
爱人如己 2024-12-03 11:43:52

我看不到任何明显的东西,但 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);

I can't see anything obvious, but asio interfaces are abysmal.

When I have problems like this, I start breaking up inline code. Given your last statement, I'd guess shared_from_this may be confusing it. If you start explicitly saying what you think all these inline things mean, you may discover your bad assumption.

boost::shared_ptr<TcpMimeConnection> temp = shared_from_this();
boost::bind(&TcpMimeConnection::match_version, temp, _1, _2);

or

boost::bind(&TcpMimeConnection::match_version, this, _1, _2);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文