Why is std :: packaged_task <void ()> not valid?
Using MSVC2012,
The following code will compile and execute as expected.
std::packaged_task< int() > task( []()->int{ std::cout << "hello world" << std::endl; return 0; } );
std::thread t( std::move(task) );
t.join();
while the following code will not be able to compile and run
std::packaged_task< void() > task( [](){ std::cout << "hello world" << std::endl; } );
std::thread t( std::move(task) );
t.join();
Why is this so?
Edit: As a workaround, you can use std :: prom to get std :: future for a function that returns void
std::promise<void> promise;
auto future = promise.get_future();
std::thread thread( [](std::promise<void> &p){ std::cout << "hello world" << std::endl; p.set_value(); }, std::move(promise) );
future.wait();
Please note that there is an error in the vs2012 library with std :: thread that forces you to pass the promise as an l-value link and transfer the promise, it will not compile if you pass the promise by value or by r-value link. This is presumably because the implementation uses std :: bind (), which does not behave as expected.
MSVC2012. , MSVC2012. , Just:: Thread: http://www.justsoftwaresolutions.co.uk/news/just-thread-v1.8.0-released.html
gcc 4.7.2:
#include <thread>
#include <future>
#include <iostream>
int main() {
std::packaged_task< void() > task( [](){ std::cout << "hello world" << std::endl; } );
std::thread t( std::move(task) );
t.join();
std::packaged_task< int() > task2( []()->int{ std::cout << "hello world" << std::endl; return 0; } );
std::thread t2( std::move(task2) );
t2.join();
}
@WhozCraig , , , MSVC2012.
struct Nothing {}; nullptr_t ?
The problem still exists in MSVS 2013RC, but I made this temporary patch while MS fixes it. This is the specialization of packaged_task for void (...), so I suggest putting this in the header file and including it after the standard headers. Please note that make_ready_at_thread_exit () is not implemented, and some functions have not been fully tested, use your own risk.
namespace std {
template<class... _ArgTypes>
class packaged_task<void(_ArgTypes...)>
{
promise<void> _my_promise;
function<void(_ArgTypes...)> _my_func;
public:
packaged_task() {
}
template<class _Fty2>
explicit packaged_task(_Fty2&& _Fnarg)
: _my_func(_Fnarg) {
}
packaged_task(packaged_task&& _Other)
: _my_promise(move(_Other._my_promise)),
_my_func(move(_Other._my_func)) {
}
packaged_task& operator=(packaged_task&& _Other) {
_my_promise = move(_Other._my_promise);
_my_func = move(_Other._my_func);
return (*this);
}
packaged_task(const packaged_task&) = delete;
packaged_task& operator=(const packaged_task&) = delete;
~packaged_task() {
}
void swap(packaged_task& _Other) {
_my_promise.swap(_Other._my_promise);
_my_func.swap(_Other._my_func);
}
explicit operator bool() const {
return _my_func != false;
}
bool valid() const {
return _my_func != false;
}
future<void> get_future() {
return _my_promise.get_future();
}
void operator()(_ArgTypes... _Args) {
_my_func(forward<_ArgTypes>(_Args)...);
_my_promise.set_value();
}
void reset() {
swap(packaged_task());
}
};
}; // namespace std