我正在尝试使用C 14 init-capture功能通过捕获在lambda中移动unique_ptr.出于某种原因,gcc和clang都拒绝编译我的代码,坚持认为我正在尝试复制一个明显不起作用的unique_ptr.我认为避免复制正是init-capture std :: move功能的要点 – 实际上,传递unique_ptr似乎是每个人使用的主要示例.
我究竟做错了什么?
#include <functional> #include <iostream> #include <memory> #include <string> void runFunc(std::function<void()>&& f) { auto ff = std::move(f); ff(); } int main() { auto ptr = std::make_unique<std::string>("hello world\n"); runFunc([captured_ptr = std::move(ptr)]() { std::cout << *captured_ptr; }); }
gcc的输出:
http://coliru.stacked-crooked.com/a/d91a480b2b6428ac
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out In file included from main.cpp:1:0: /usr/local/include/c++/5.2.0/functional: In instantiation of 'static void std::_Function_base::_Base_manager<_Functor>::_M_clone(std::_Any_data&,const std::_Any_data&,std::false_type) [with _Functor = main()::<lambda()>; std::false_type = std::integral_constant<bool,false>]': /usr/local/include/c++/5.2.0/functional:1746:16: required from 'static bool std::_Function_base::_Base_manager<_Functor>::_M_manager(std::_Any_data&,std::_Manager_operation) [with _Functor = main()::<lambda()>]' /usr/local/include/c++/5.2.0/functional:2260:19: required from 'std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = main()::<lambda()>; <template-parameter-2-2> = void; _Res = void; _ArgTypes = {}]' main.cpp:15:6: required from here /usr/local/include/c++/5.2.0/functional:1710:34: error: use of deleted function 'main()::<lambda()>::<lambda>(const main()::<lambda()>&)' __dest._M_access<_Functor*>() = ^ main.cpp:13:43: note: 'main()::<lambda()>::<lambda>(const main()::<lambda()>&)' is implicitly deleted because the default definition would be ill-formed: runFunc([captured_ptr = std::move(ptr)]() { ^ main.cpp:13:43: error: use of deleted function 'std::unique_ptr<_Tp,_Dp>::unique_ptr(const std::unique_ptr<_Tp,_Dp>&) [with _Tp = std::__cxx11::basic_string<char>; _Dp = std::default_delete<std::__cxx11::basic_string<char> >]' In file included from /usr/local/include/c++/5.2.0/memory:81:0,from main.cpp:3: /usr/local/include/c++/5.2.0/bits/unique_ptr.h:356:7: note: declared here unique_ptr(const unique_ptr&) = delete;
clang的输出:
http://coliru.stacked-crooked.com/a/4374988d875fcedc
In file included from main.cpp:1: /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/functional:1711:10: error: call to implicitly-deleted copy constructor of '(lambda at main.cpp:13:13)' new _Functor(*__source._M_access<_Functor*>()); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/functional:1746:8: note: in instantiation of member function 'std::_Function_base::_Base_manager<(lambda at main.cpp:13:13)>::_M_clone' requested here _M_clone(__dest,__source,_Local_storage()); ^ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/functional:2260:33: note: in instantiation of member function 'std::_Function_base::_Base_manager<(lambda at main.cpp:13:13)>::_M_manager' requested here _M_manager = &_My_handler::_M_manager; ^ main.cpp:13:13: note: in instantiation of function template specialization 'std::function<void ()>::function<(lambda at main.cpp:13:13),void>' requested here runFunc([captured_ptr = std::move(ptr)]() { ^ main.cpp:13:14: note: copy constructor of '' is implicitly deleted because field '' has a deleted copy constructor runFunc([captured_ptr = std::move(ptr)]() { ^ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/unique_ptr.h:356:7: note: 'unique_ptr' has been explicitly marked deleted here unique_ptr(const unique_ptr&) = delete; ^ 1 error generated.
解决方法
因为
std::function
必须是可复制的:
std::function
satisfies the requirements of CopyConstructible and CopyAssignable.
而有问题的constructor:
Initializes the target with a copy of
f
.
您正在构建的lambda(完全有效)具有unique_ptr成员,这使得它不可复制.如果你重写了runFunc以按值获取任意仿函数:
template <typename F> void runFunc(F f) { auto ff = std::move(f); ff(); }
它会编译.