相互递归的lambdas

时间:2013-03-13 19:26:02

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

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

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

我不得不以更冗长的方式写这篇文章。一些C ++专家可以帮助我定义相互递归的lambdas吗?

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:存在生命周期问题,因此无效。

1 个答案:

答案 0 :(得分:4)

回答我自己的问题:

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

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

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

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

  4. 所以我认为这接近我需要做的事情:

    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];
    };