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

vs2012 ライブラリには std::thread のバグがあり、promise を l-value 参照として渡し、promise を移動する必要があることに注意してください。promise を値または r- で渡すとコンパイルされません。値参照。これは、実装が期待どおりに動作しない std::bind() を使用しているためと考えられます。

4

3 に答える 3

6

これは MSVC2012 のバグです。MSVC2012 に同梱されているスレッド ライブラリの実装には、かなりの数のバグがあります。商用の Just:: Threadライブラリと比較した部分的なリストをブログ投稿に投稿しました。

于 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 {};またはnullptr_tを戻り値として使用してみてください。

于 2013-02-07T16:21:44.227 に答える
2

問題は MSVS 2013RC でもまだ残っていますが、MS が修正するまでの間、この一時的なパッチを作成しました。これは void(...) 用の packaged_task の特殊化であるため、これをヘッダー ファイルに入れ、標準ヘッダーの後に含めることをお勧めします。あなた自身のリスク。

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 に答える