簡體   English   中英

帶有unique_ptr捕獲的asio lambda

[英]asio lambda with unique_ptr capture

我正在使用asio獨立1.10.6和vs2015 rc。

vs2015支持unique_ptr捕獲。 所以我寫了一些代碼如下:

auto data = std::make_unique<std::string>("abc");
auto buffer = asio::buffer(data->c_str(), data->size());
asio::async_write(s, buffer, [data = std::move(data)](
  const asio::error_code& error, size_t byte_transferred) mutable {
  do_something(std::move(data), error, byte_transferred);
});

但是當我編譯代碼時,編譯器說:

錯誤C2280:....試圖引用已刪除的函數

據我所知,它說我嘗試復制lambda,因為lambda捕獲了一個std::unique_ptr ,所以它是不可復制的。

令我困惑的是為什么asio想要復制lambda而不是移動lambda。

我的代碼出了什么問題? 如何解決它?

=========================

完整的代碼是:

void do_something(std::unique_ptr<std::string> data) { }

void compile_failed() {
  asio::io_service io_service;
  asio::ip::tcp::socket s(io_service);

  auto data = std::make_unique<std::string>("abc");
  auto buffer = asio::buffer(data->c_str(), data->size());

  asio::async_write(s, buffer, [data = std::move(data)](const asio::error_code& error,
    size_t byte_transferred) mutable {
    do_something(std::move(data));
  });
}

template<typename T > struct lambda_evil_wrap {
  mutable T ptr_;
  lambda_evil_wrap(T&& ptr) : ptr_(std::forward< T>(ptr)) {}
  lambda_evil_wrap(lambda_evil_wrap const& other) : ptr_(std::move(other.ptr_)) {}
  lambda_evil_wrap & operator=(lambda_evil_wrap& other) = delete;
};

void compile_success_but_very_danger() {
  asio::io_service io_service;
  asio::ip::tcp::socket s(io_service);

  auto data = std::make_unique<std::string>("abc");
  auto buffer = asio::buffer(data->c_str(), data->size());

  lambda_evil_wrap<std::unique_ptr<std::string>> wrapper(std::move(data));
  asio::async_write(s, buffer, [wrapper](const asio::error_code& error,
    size_t byte_transferred) mutable {
    do_something(std::move(wrapper.ptr_));
  });
}

int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}

作為代碼,如果我將unique_ptr包裝到可復制對象,則編譯就可以了。 但是lambda_evil_wrap :: lambda_evil_wrap(lambda_evil_wrap const&a)真的很糟糕且不安全。 我不知道asio作者是否寫了一些代碼如下:

Handler handler2(handler);
handler(...); // Crash here

原始代碼中的錯誤是處理程序無法滿足Handler類型要求,因為它不是CopyConstructible

處理程序必須滿足CopyConstructible類型(C ++ Std,20.1.3)的要求。

正如Boost.Asio的C ++ 11對可移動處理程序的支持所述,在可能的情況下,Boost.Asio將優先於復制構造函數的移動構造函數,但處理程序仍必須是可復制構造的:

[...] Boost.Asio的實現將使用處理程序的移動構造函數而不是其復制構造函數。 在某些情況下,Boost.Asio可能能夠消除對處理程序的復制構造函數的所有調用。 但是,處理程序類型仍然需要是可復制構造的。

要解決此問題,可以考慮使用std::shared_ptr而不是std::unique_ptr ,從而使lambda可以復制構造。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM