对 boost asio 完成处理程序的右值引用

Posted

技术标签:

【中文标题】对 boost asio 完成处理程序的右值引用【英文标题】:rvalue reference to boost asio completion handler 【发布时间】:2015-03-17 23:53:59 【问题描述】:

在 boost::asio 中,是否可以使用 C++11 中的移动语义和右值引用模拟来创建和实现完成处理程序?

我的尝试如下,但我不明白出现错误的原因:

类定义:

struct SocketTest : std::enable_shared_from_this<SocketTest> 


  SocketTest(boost::asio::ip::udp::socket socket):socket_(std::move(socket))

  template<typename Handler>
  void async_receive(dummy dummy,Handler&& handler)
    auto self(shared_from_this());

    socket_.async_receive(boost::asio::buffer(buf_), 
       std::bind([this,self](
          boost::system::error_code ec, 
          std::size_t bytes_transferred, 
          Handler&& moved_handler
       )
           moved_handler(ec,bytes_transferred);
        , std::move(handler)));

  

  std::array<char,max_length> buf_;
  boost::asio::ip::udp::socket socket_;
;

类调用示例:

SocketTest socket_test(std::move(s));

socket_test.async_receive(dummy(), []( boost::system::error_code ec, std::size_t bytes_transferred)
    // many cool things accomplished!
);

似乎复制处理程序的以下版本可以正常工作,但我有兴趣学习如何避免该复制:

struct SocketTest : std::enable_shared_from_this<SocketTest> 


  SocketTest(boost::asio::ip::udp::socket socket):socket_(std::move(socket))

  template<typename Handler>
  void async_receive(dummy dummy,Handler handler)
    auto self(shared_from_this());

    socket_.async_receive(boost::asio::buffer(buf_), [this,self,handler](boost::system::error_code ec, std::size_t bytes_transferred)
       handler(ec,bytes_transferred);

    );

  

  std::array<char,max_length> buf_;
  boost::asio::ip::udp::socket socket_;
;

The full source and errors can be found here

【问题讨论】:

【参考方案1】:

您不能 bind 对采用右值引用的可调用对象,因为当 bind 保存其参数时,它不再是右值。在您的情况下,您可以让它按值接受Handler(这是存储处理程序的最终位置)。您可以查看this question了解更多详情。

另外,您忘记为bind 提供占位符:

socket_.async_receive(boost::asio::buffer(buf_), 
   std::bind([this,self](
      boost::system::error_code ec, 
      std::size_t bytes_transferred, 
      Handler moved_handler
   // ^^^^^^^ passing by value 
   )
       moved_handler(ec,bytes_transferred);
    , std::placeholders::_1, std::placeholders::_2, std::move(handler)));
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ placeholders added

【讨论】:

以上是关于对 boost asio 完成处理程序的右值引用的主要内容,如果未能解决你的问题,请参考以下文章

对临时声明的右值引用

重新理解C11的右值引用

编译器对超出范围的变量的右值引用进行推断

C11新特性右值引用&&

深入思考右值引用

转载C++ 11中的右值引用