I'd like to capture a variable of type std::vector<std::unique_ptr<MyClass>>
in a lambda expression (in other words, "capture by move"). I found a solution which uses std::bind to capture unique_ptr (https://stackoverflow.com/a/12744730/2478832) and decided to use it as a starting point. However, the most simplified version of the proposed code I could get doesn't compile (lots of template mistakes, it seems to try to call unique_ptr's copy constructor).
#include <functional>
#include <memory>
std::function<void ()> a(std::unique_ptr<int>&& param)
{
return std::bind( [] (int* p) {},
std::move(param));
}
int main()
{
a(std::unique_ptr<int>(new int()));
}
Can anybody point out what is wrong with this code?
EDIT: tried changing the lambda to take a reference to unique_ptr, it still doesn't compile.
#include <functional>
#include <memory>
std::function<void ()> a(std::unique_ptr<int>&& param)
{
return std::bind( [] (std::unique_ptr<int>& p) {}, // also as a const reference
std::move(param));
}
int main()
{
a(std::unique_ptr<int>(new int()));
}
Here's Visual Studio 2012 output:
1>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\tuple(151): error C2248: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<int,std::default_delete<_Ty>>'
1> with
1> [
1> _Ty=int
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1447) : see declaration of 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr'
1> with
1> [
1> _Ty=int
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\tuple(521) : see reference to function template instantiation 'std::_Tuple_val<_This>::_Tuple_val<const _Ty&>(_Other)' being compiled
1> with
1> [
1> _This=std::unique_ptr<int,std::default_delete<int>>
1> , _Ty=std::unique_ptr<int,std::default_delete<int>>
1> , _Other=const std::unique_ptr<int,std::default_delete<int>> &
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\tuple(521) : see reference to function template instantiation 'std::_Tuple_val<_This>::_Tuple_val<const _Ty&>(_Other)' being compiled
1> with
1> [
1> _This=std::unique_ptr<int,std::default_delete<int>>
1> , _Ty=std::unique_ptr<int,std::default_delete<int>>
1> , _Other=const std::unique_ptr<int,std::default_delete<int>> &
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\tuple(521) : while compiling class template member function 'std::tuple<std::unique_ptr<int,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::tuple(const std::tuple<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> &)'
1> with
1> [
1> _Ty=int
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(1152) : see reference to function template instantiation 'std::tuple<std::unique_ptr<int,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::tuple(const std::tuple<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> &)' being compiled
1> with
1> [
1> _Ty=int
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(1152) : see reference to class template instantiation 'std::tuple<std::unique_ptr<int,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>' being compiled
1> with
1> [
1> _Ty=int
1> ]
1> main.cpp(15) : see reference to class template instantiation 'std::_Bind<false,void,a::<lambda_2ad08ede4c4ce9c02d5497417b633d1d>,std::unique_ptr<int,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>' being compiled
1> with
1> [
1> _Ty=int
1> ]
[] (std::unique_ptr<int> && p) {}
instead of[] (int* p) {}
– Nawaza
should take thestd::unique_ptr
through an rvalue-reference – David Rodríguez - dribeas&&
when you need to differentiate between lvalue and rvalue. This is not the case here, and there is no reason not to take the argument toa
by reference: by-value suffices. The case of the lambda is different, in this case the signature is saying that the argument to the lambda is a temporary from which you can freely move and destroy the original, but the fact is that it is not a temporary, it is astd::unique_ptr
that lives inside the bound object. If you move out of it, subsequent calls to thestd::function<void()>
will cause a call with null. – David Rodríguez - dribeas