c++ - Boost.Asio:不能使用 std::bind() 来指定回调

标签 c++ c++11 boost boost-asio

我正在尝试使用 Boost.Asio 的 async_read_until()免费函数,但我无法使用 std::bind() 将成员函数指定为回调.我对其他 Boost.Asio 函数使用这个习惯用法没有问题,所以我很困惑为什么它不适用于 async_read_until() .

这是我的例子:

#include <functional>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

class Test
{
public:
    boost::asio::streambuf buf;
    boost::asio::ip::tcp::socket sock;

    Test(boost::asio::io_service& io) :
        sock(io)
    {
    }

    void readComplete(const boost::system::error_code& error,
                      std::size_t bytesTransferred)
    {
    }

    void invoke()
    {
        boost::asio::async_read_until(sock,
                                      buf,
                                      '\n',
                                      std::bind(&Test::readComplete,
                                                this,
                                                boost::asio::placeholders::error,
                                                boost::asio::placeholders::bytes_transferred));
    }
};

int main(int argc, char** argv)
{
    boost::asio::io_service io;
    Test t(io);

    t.invoke();

    return 0;
}

在这种情况下,编译失败并出现以下错误(以及其他 template-compiler-error-barf):

In file included from /home/me/eclipse-workspace/practice/main.cpp:4:
In file included from /usr/include/boost/asio.hpp:91:
In file included from /usr/include/boost/asio/read_until.hpp:921:
/usr/include/boost/asio/impl/read_until.hpp:707:3: error: static_assert failed "ReadHandler type requirements not met"
  BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/asio/detail/handler_type_requirements.hpp:153:3: note: expanded from macro 'BOOST_ASIO_READ_HANDLER_CHECK'
  BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
  ^
/usr/include/boost/asio/detail/handler_type_requirements.hpp:105:6: note: expanded from macro 'BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT'
     static_assert(expr, msg);
     ^             ~~~~
/home/me/eclipse-workspace/practice/main.cpp:24:22: note: in instantiation of function template specialization 'boost::asio::async_read_until<boost::asio::basic_stream_socket<boost::asio::ip::tcp,
      boost::asio::stream_socket_service<boost::asio::ip::tcp> >, std::allocator<char>, std::_Bind<std::_Mem_fn<void (Test::*)(const boost::system::error_code &, unsigned long)>
      (Test *, boost::arg<1> (*)(), boost::arg<2> (*)())> >' requested here
        boost::asio::async_read_until(sock,
                     ^

所以它告诉我我的函数签名是错误的,但它似乎不是。

我不明白为什么它不起作用,而且我更不明白的是,如果我只是换出 std::bind()对于 boost::bind() ,它构建和工作完全正常。有人可以帮助我理解这一点吗?

仅供引用,我正在使用 Boost 1.58.0(来自 Ubuntu 16.04 Universe 存储库)和带有 C++11 的 clang++ 3.8。

最佳答案

不幸的是,您正在混合和匹配 bind:

std::bind(&Test::readComplete,
    this,
    boost::asio::placeholders::error,
    boost::asio::placeholders::bytes_transferred));

boost::asio::placeholders 仅适用于 boost::bind,不适用于 std::bind

来自 the docs ,你想要:

std::bind(&Test::readComplete,
    this,
    std::placeholders::_1,
    std::placeholders::_2));

boost::bind(&Test::readComplete,
    this,
    boost::asio::placeholders::error,
    boost::asio::placeholders::bytes_transferred)); 

我不明白为什么boost不直接说它的占位符是std占位符:

namespace std {
    template <int I>
    struct is_placeholder<boost::arg<I>>
        : integral_constant<int, I>
    { };
}

我认为这是有充分理由的?

关于c++ - Boost.Asio:不能使用 std::bind() 来指定回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52041514/

相关文章:

c++ - C++中的隐式类型转换字母

c++ - 作为模板参数的函数的多态签名(使用 lambda)

c++ - 为什么 C++ 中的 lambda 永远不会 DefaultConstructible

c++ - 我已经编写了 C++ 代码来将 boost::optional 视为一个范围,但它无法编译

c++ - Boost hana 获取字符串中的类型

C++ 运算符重载和继承

c++ - 快速将 uint32_t 转换为二进制

c++ - 使用由 Boost : did not match C++ signature 生成的 Python 模块

c++ - kde 固定按钮 API

c++ - weak_ptr 奇怪的复制构造函数