I have a function which enqueue lambda using std::queue's
build-in emplace. I created shared_ptr
object (task), which later I would capture in lambda.
template<typename Func, typename... Args>
auto submit(Func&& f, Args&&... args)
{
using result_type = std::result_of_t<Func(Args...)>;
using pckg_task_type = std::packaged_task<result_type()>;
auto task = std::make_shared< pckg_task_type >(
std::bind(std::forward<Func>(f), std::forward<Args>(args)...) );
...
}
This is the part which is creating confusion:
Case 1: Which works perfectly
tasks.emplace(
[task](){
auto wptr = std::weak_ptr<pckg_task_type>(task);
if( auto p = wptr.lock() )
{
(*p)();
}
else
throw std::runtime_error("weak error");
}
);
Case 2: Which immediately throws an exception
tasks.emplace(
[wc = std::weak_ptr<pckg_task_type>(task)](){
if( auto p = wc.lock() )
{
(*p)();
}
else
throw std::runtime_error("weak error");
}
);
With tasks defined as
std::queue< std::function<void()> > tasks;
Calling lambda from case 2 without emplace it into queue doesn't throw exception.
Can anyone explain the difference between cases above? Where is the problem?