How do we return a std::function
that contains std::unique_ptr
from a generic lambda capture in C ++ 14? In particular, in the following code
// For std::function #include <functional> // For std::iostream #include <iostream> // For std::unique_ptr #include <memory> #if 0 std::function <void()> make_foo() { auto x = std::make_unique <int> (3); return [x=std::move(x)]() { std::cout << *x << std::endl; }; } #endif int main() { auto x = std::make_unique <int> (3); auto foo = [x=std::move(x)]() { std::cout << *x << std::endl; }; foo(); }
Everything works fine at startup with GCC 4.9.2 and C ++ 14 enabled. In particular, this shows that generalized lambda captures work. However, when we change the code where #if 1
, we get a compilation error:
g++ -g -std=c++14 test01.cpp -o test01 In file included from test01.cpp:4:0: /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/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 = make_foo()::<lambda()>; std::false_type = std::integral_constant<bool, false>]': /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/functional:1914:51: required from 'static bool std::_Function_base::_Base_manager<_Functor>::_M_manager(std::_Any_data&, const std::_Any_data&, std::_Manager_operation) [with _Functor = make_foo()::<lambda()>]' /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/functional:2428:19: required from 'std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = make_foo()::<lambda()>; <template-parameter-2-2> = void; _Res = void; _ArgTypes = {}]' test01.cpp:17:5: required from here /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/functional:1878:34: error: use of deleted function 'make_foo()::<lambda()>::<lambda>(const make_foo()::<lambda()>&)' __dest._M_access<_Functor*>() = ^ test01.cpp:15:27: note: 'make_foo()::<lambda()>::<lambda>(const make_foo()::<lambda()>&)' is implicitly deleted because the default definition would be ill-formed: return [x=std::move(x)]() { ^ test01.cpp:15:27: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]' In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/memory:81:0, from test01.cpp:10: /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/bits/unique_ptr.h:356:7: note: declared here unique_ptr(const unique_ptr&) = delete; ^ Makefile:2: recipe for target 'all' failed make: *** [all] Error 1
Now, given that the returned function contains std::unique_ptr
, it makes sense that we cannot copy the resulting std::function
. However, since we are returning the lambda function created on the fly, should this not be the r-value and the correct definition? Basically, is there a way to fix make_foo
where we still have a generic lambda capture of a std::unique_ptr
?
source share