【问题标题】:Boost.Asio lambda capture failed to compileBoost.Asio lambda 捕获无法编译
【发布时间】:2020-08-23 23:23:12
【问题描述】:

我发现我无法移动 Asio 套接字对象 boost::asio::ip::tcp::socket&& 为 boost::asio::write() 函数的 lambda。为了尝试编译结果,我将案例整理成下面的测试程序。

如果我取消注释 boost::asio::write(sock,... 行,clang 和 gcc 都指责没有 sock.write_some() 方法...但是库中提供了 boost::asio::ip::tcp::socket::write_some()!

测试代码:

// to build:
// clang++ -Wall -std=c++17 -o test_asio_lambda_clang test_asio_lambda.cpp
// g++-9 -Wall -std=c++17 -o test_asio_lambda_gcc test_asio_lambda.cpp

#include<boost/asio.hpp>
#include<iostream>
#include<type_traits>

int main()
{
  auto foo=[](boost::asio::ip::tcp::socket s){
    auto bar=[&s,sock{std::move(s)}](){

      std::cout<<"std::is_same<decltype(sock),decltype(s)>::value = "<<std::is_same<decltype(sock),decltype(s)>::value<<std::endl;
      std::cout<<"std::is_same<decltype(sock),boost::asio::ip::tcp::socket>::value = "<<std::is_same<decltype(sock),boost::asio::ip::tcp::socket>::value<<std::endl;

      //boost::asio::write(sock,boost::asio::buffer(std::string{"Hello, folk!\n"}));
    };


    bar();
  };

  boost::asio::io_context io_context;
  boost::asio::ip::tcp::socket sock{io_context};
  foo(std::move(sock));
}

所以,我注释掉这一行并使用std::is_same 检查类型来测试类型,因为我认为sock 和s 的类型应该是boost::asio::ip::tcp::socket 和代码boost::asio::write(sock,...) 应该编译。

clang和gcc的结果不一样!

我不知道出了什么问题...我的编码问题、编译器错误、boost.asio 错误?

$ ./test_asio_lambda_clang 
std::is_same<decltype(sock),decltype(s)>::value = 1
std::is_same<decltype(sock),boost::asio::ip::tcp::socket>::value = 1
$ ./test_asio_lambda_gcc
std::is_same<decltype(sock),decltype(s)>::value = 0
std::is_same<decltype(sock),boost::asio::ip::tcp::socket>::value = 0

【问题讨论】:

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


    【解决方案1】:

    boost::asio::write 通过非常量引用获取sock。这意味着sock 受此功能影响。

    sock 是 lambda 生成的闭包的数据成员。默认情况下,闭包的函数调用运算符标记为const。因此,您只能将 sock 传递给其他 const 函数。

    如果你想让 lambda 修改 sock 你必须添加 mutable 关键字:

    auto bar=[&s,sock{std::move(s)}]() mutable {
    

    【讨论】:

    • 谢谢!这就是为什么编译器抱怨没有 write_some() 因为它不是 const。顺便说一句,关于 asio 编程,最好使用 lambda 或 std::bind?
    • @VictorTsang 很难说哪个更好。他们都做同样的工作。 Under this link 是关于 bind vs lambda 的一个很好的总结,它并不严格涉及在 Asio 中的使用,但值得一读。
    猜你喜欢
    • 2016-12-15
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-24
    • 1970-01-01
    相关资源
    最近更新 更多