Basically I'm trying to create a lambda that captures an object that is moveable only (e.g unique_ptr), and take some argument as input.
I have an expensive resource that is raised by callback which I need to move to another thread for processing. The object is moveable only (and this cannot change) and the callback signature takes it by value (can be changed to rvalue reference). The following is a minimal working example of the problem at state:
void processor(std::function<void(int)> func)
{
auto thread = std::async(std::launch::async, func, 2);
}
using ResourceType = std::unique_ptr<int>; //Example for moveable only type
void handler(ResourceType r)
{
processor([r](int x) // error C2280: ...unique_ptr...: attempting to reference a deleted function
{
int usage_of_resource = *r + x;
std::cout << usage_of_resource << std::endl;
});
}
I tried following this question and answers (How to capture a unique_ptr into a lambda expression?) But, I can't use C++14 and the suggested answer there doesn't even compile. This is what I tried:
std::function<void(int)> getAction(ResourceType p)
{
return std::bind([](ResourceType& r, int x)
{
int usage_of_resource = *r + x;
std::cout << usage_of_resource << std::endl;
}, std::move(p), std::placeholders::_1);
}
void handler(ResourceType r)
{
processor(getAction(std::move(r)));
}
g++: error: use of deleted function
msvc: error: attempting to reference a deleted function
I have tried to sort of create my own lambda (using a struct
with operator()
) but I failed to get around the same issue. Eventually as a workaround I created a new pointer to my resource, and moved it there before calling the processor and then extracting it inside the lambda I pass.
Is this a real issue with the C++ standard that is only solved in C++14? or is there a way to move the object somehow (preferably an elegant one of course)?
EDIT:
Capturing the underlying resource would potentially cause a memory leak, since the processor is a fixed size message queue that drops the first element (dequeues) when the queue is full and a new element arrives. So between the time of capture and the time of usage the lambda can be dropped and thus the resource would not be freed.