2

这是一个基于boost asio 示例的 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:存在生命周期问题,因此无法正常工作。

4

1 回答 1

4

回答我自己的问题:

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

  1. 我一直小心地将and复制到相应的闭包中,以便在构造函数超出范围时可以使用它们。不幸的是,闭包与构造函数同时超出范围。因此,复制是没有意义的。receivedrecv_from[&, 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-03-13T20:20:19.793 回答