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

时间:2011-07-26 20:01:48

标签: c++ boost boost-asio

以下代码编译并与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*\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&gt;,boost :: _ mfi :: mf2,bool&gt;,sapphire :: transport: :ip :: TcpMimeConnection,boost :: asio :: buffers_iterator,boost :: asio :: buffers_iterator&gt;,boost :: _ bi :: list3&gt ;, boost :: arg&lt; 1&gt ;, boost :: arg&lt; 2&gt;&gt; ;&gt;&amp;)'含糊不清 [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&gt;,boost :: _ mfi :: mf2,bool&gt;,sapphire :: transport :: ip :: TcpMimeConnection,boost :: asio :: buffers_iterator,boost: :asio :: buffers_iterator&gt;,boost :: _ bi :: list3&gt;,boost :: arg&lt; 1&gt ;, boost :: arg&lt; 2&gt; &GT; &gt;,T = boost :: _ bi :: bind_t,bool&gt;,boost :: _ mfi :: mf2,bool&gt;,sapphire :: transport :: ip :: TcpMimeConnection,boost :: asio :: buffers_iterator,boost :: asio :: buffers_iterator&gt;,boost :: _ bi :: list3&gt;,boost :: arg&lt; 1&gt ;, boost :: arg&lt; 2&gt; &GT; &GT;] [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,bool&gt;,boost :: _ mfi :: mf2,bool&gt;,sapphire :: transport :: ip :: TcpMimeConnection,boost :: asio :: buffers_iterator,boost :: asio :: buffers_iterator&gt;,boost :: _ bi :: list3&gt;,boost :: arg&lt; 1&gt ;, boost :: arg&lt; 2&gt; &GT; &gt;,T = boost :: _ bi :: bind_t,bool&gt;,boost :: _ mfi :: mf2,bool&gt;,sapphire :: transport :: ip :: TcpMimeConnection,boost :: asio :: buffers_iterator,boost :: asio :: buffers_iterator&gt;,boost :: _ bi :: list3&gt;,boost :: arg&lt; 1&gt ;, boost :: arg&lt; 2&gt; &GT; &GT;] [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&gt;&amp;,boost :: asio :: basic_streambuf &gt;&amp;,boost :: _ bi :: bind_t,bool&gt;,boost :: _ mfi :: mf2,bool&gt;,sapphire :: transport :: ip :: TcpMimeConnection,boost :: asio :: buffers_iterator,boost :: asio :: buffers_iterator&gt;,boost :: _ bi :: list3&gt;,boost :: arg&lt; 1&gt ;, boost :: arg&lt; 2&gt;&gt;&gt;,boost :: asio :: detail :: wrapped_handler,boost :: _bi :: list4&gt ;, boost :: _ bi :: value,boost :: arg&lt; 1&gt;()(),boost :: arg&lt; 2&gt;()()&gt;&gt;&gt; )'

当我简单地将boost :: regex(“MIME-Version:\ s * 1.0 \ s * \ r \ n”,boost :: regex :: icase)传递给async_read_until(第三次重载)时没有问题,但我想自定义async_read_until(第四次重载)的匹配条件,当我将匹配条件设置为成员函数时遇到了问题。我需要match_version作为成员函数,因为没有办法告诉处理程序返回的原因(找到大小或匹配)。所以我知道问题在于boost :: bind(&amp; TcpMimeConnection :: match_version,shared_from_this(),_ 1,_2), 代码行,但我不知道如何解决它。

3 个答案:

答案 0 :(得分:2)

似乎为了使用绑定器作为匹配,您需要为此类型专门化boost::asio::is_match_condition,即使the documentation state定义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 {};
 }
}

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

答案 1 :(得分:0)

我看不到任何明显的东西,但asio界面非常糟糕。

当我遇到这样的问题时,我开始分解内联代码。鉴于你最后的陈述,我猜想shared_from_这可能会令人困惑。如果你开始明确地说出你所认为的所有这些内联事物的意思,你可能会发现你的错误假设。

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

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

答案 2 :(得分:0)

这是我根据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 {namespace asio {

template <> struct is_match_condition< MatchVersion >
: public boost::true_type {};

}}

namespace sapphire {namespace transport {namespace 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;
}

}}}