8

使用 MSVC2012,

以下代码将按预期编译和运行

std::packaged_task< int() > task( []()->int{ std::cout << "hello world" << std::endl; return 0; } );
std::thread t( std::move(task) );
t.join();

而以下代码将无法编译和运行

std::packaged_task< void() > task( [](){ std::cout << "hello world" << std::endl; } );
std::thread t( std::move(task) );
t.join();

为什么会这样?

编辑:作为一种解决方法,可以使用 std::promise 在返回 void 的函数上获取 std::future

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();

请注意,在带有 std::thread 的 vs2012 库中存在一个错误,该错误会强制您将承诺作为左值引用传入并将承诺移入,如果您通过值或通过 r- 传递承诺,它将无法编译价值参考。这可能是因为实现使用了 std::bind() ,它的行为不符合预期。

4

3 回答 3

6

这是 MSVC2012 中的错误。MSVC2012 附带的线程库实现中有很多错误。我在我的博客文章中发布了一个部分列表,将其与我的商业 Just::Thread 库进行了比较:http ://www.justsoftwaresolutions.co.uk/news/just-thread-v1.8.0-released.html

于 2013-02-07T16:57:11.203 回答
4

这适用于 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 {};ornullptr_t作为您的返回值?

于 2013-02-07T16:21:44.227 回答
2

这个问题在 MSVS 2013RC 中仍然存在,但我在 MS 纠正它时制作了这个临时补丁。它是 void(...) 的 packaged_task 的一个特化,所以我建议把它放在一个头文件中,并将它包含在标准头文件之后。注意 make_ready_at_thread_exit() 没有实现,一些功能没有经过完全测试,使用 at你自己的风险。

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
于 2013-10-17T15:39:33.963 回答