【问题标题】:Mutually recursive lambdas相互递归的 lambda
【发布时间】:2013-03-13 19:26:01
【问题描述】:

这是一个基于 boost asio example 的 boost::asio udp echo 演示。

使用 C++ lambda 的这个版本的内容不到 boost 示例的一半,但 gcc 告诉我 receivedrecv_from 中不可见。

不得不以更冗长的方式来写这篇文章让我很痛苦。一些 C++ 大师可以帮助我定义相互递归的 lambda 表达式吗?

class server {
public:
  server(io_service& io_service, short port)
    : socket_(io_service, udp::endpoint(udp::v4(), port)) {
    auto recv_from = [&,received]() {
      socket_.async_receive_from(buffer(data_, max_length), sender_endpoint_,
                                 received);
    };
    auto received = [&,recv_from](const error_code& error, size_t bytes_transferred) {
      if (!error && bytes_transferred > 0) {
        socket_.async_send_to(buffer(data_, bytes_transferred), sender_endpoint_,
                              [&](const error_code&, size_t) {
                                recv_from();
                              });
      } else {
        recv_from(); // loop
      }
    };
    recv_from();
  }

private:
  udp::socket socket_;
  udp::endpoint sender_endpoint_;
  enum { max_length = 1024 };
  char data_[max_length];
};

编辑,解决方案:我需要添加这个:

std::function<void(const error_code&, size_t)> received;

让类型推理引擎更容易(我被 Haskell 编程过宠坏了)

Edit2:存在生命周期问题,因此无法正常工作。

【问题讨论】:

  • 你使用普通的static函数怎么样?问题消失了,更具可读性。
  • 我看到我的问题可能与这个问题重复:stackoverflow.com/questions/2067988/…
  • +Seth Carnegie 对于静态函数,它的可读性较差,因为样板要多 50%。
  • 哦,我看到你正在使用捕获。然后使用非静态函数。几乎没有任何额外的样板,如果有的话。
  • 请注意,std::function&lt;void(const error_code&amp;, size_t)&gt; 有成本(它是动态调度的)。此外,不要用答案编辑您的问题,而是自行回答您的问题,然后将其标记为正确答案。 :)

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


【解决方案1】:

回答我自己的问题:

我的代码实际上有不少于三个问题。

  1. 我一直小心地将receivedrecv_from 复制到相应的闭包中,以便在构造函数超出范围时它们可以使用。 不幸的是,闭包go out of scope 与构造函数同时关闭。因此,[&amp;, xxx] 复制 xxx 是没有意义的。

  2. 必须修复至少(?)其中一个 lambda 表达式的类型以取悦类型推理引擎。

  3. 但这并不能解决问题 #1。为了解决生命周期问题,我应该将闭包对象存储在 server 对象中。

所以我认为这接近我需要做的:

class server {
 public:
   server(io_service& io_service, short port)
     : socket_(io_service, udp::endpoint(udp::v4(), port)) {
    recv_from = [&]() {
       socket_.async_receive_from(buffer(data_, max_length), sender_endpoint_,
                                 received);
    };
    received = [&](const error_code& error, size_t bytes_transferred) {
      if (!error && bytes_transferred > 0) {
        socket_.async_send_to(buffer(data_, bytes_transferred), sender_endpoint_,
                              [&](const error_code&, size_t) {
                                recv_from();
                              });
      } else {
        recv_from(); // loop
      }
    };
    recv_from();
  }

private:
  udp::socket socket_;
  udp::endpoint sender_endpoint_;
  std::function<void(const error_code&, size_t)> received;
  std::function<void()> recv_from;
  enum { max_length = 1024 };
  char data_[max_length];
};

【讨论】:

    猜你喜欢
    • 2013-12-13
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    相关资源
    最近更新 更多