我正在使用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捕获了a 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将首选move构造函数而不是copy构造函数,但该处理程序仍必须是可复制构造的:
[...] Boost.Asio的实现将优先使用处理程序的move构造函数,而不是其复制构造函数。在某些情况下,Boost.Asio可能能够消除对处理程序的副本构造函数的所有调用。但是,处理程序类型仍然需要可复制构造。
要解决此问题,可以考虑使用std::shared_ptr
代替std::unique_ptr
,从而使lambda具有可复制构造性。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句