Boost.Asio lambda捕获编译失败

问题描述 投票:0回答:1

我发现我无法移动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检查类型以测试类型,因为我认为socks的类型应为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个回答
2
投票

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

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

如果要让lambda修改sock,则必须添加mutable关键字:

auto bar=[&s,sock{std::move(s)}]() mutable {
© www.soinside.com 2019 - 2024. All rights reserved.