Не удалось скомпилировать лямбда-захват Boost.Asio - PullRequest
0 голосов
/ 08 мая 2020

Я обнаружил, что не могу переместить объект сокета Asio boost::asio::ip::tcp::socket&& в лямбду для функции boost::asio::write(). Я сокращаю этот случай в тестовой программе ниже, чтобы проверить результаты компилятора.

Если я раскомментирую строку boost::asio::write(sock,..., оба clang и g cc будут обвинять в отсутствии метода 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 и g cc разные!

Понятия не имею, что не так .. Моя проблема с кодированием, ошибка компилятора, ошибка 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

1 Ответ

2 голосов
/ 08 мая 2020

boost::asio::write принимает sock по неконстантной ссылке. Это означает, что эта функция влияет на sock.

sock - член данных замыкания, сгенерированный лямбдой. По умолчанию оператор закрытия вызова функции помечен как const. Таким образом, вам разрешено передавать sock другим функциям const .

Если вы хотите, чтобы лямбда изменяла sock, вам нужно добавить mutable ключевое слово:

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