2016-10-12 5 views
0

std :: packaged_taskのコピーコンストラクターが不足しているため、std :: functionに渡すことができません。ダミーコピーコンストラクターをstd :: packaged_taskに追加する

私はstd :: packaged_taskから継承し、ダミーコピーコンストラクタを追加しました。これは移動されたstd ::関数をコピーしないと呼び出されないはずです。 GCC 6.2.1でこれをコンパイルする

#include <iostream> 
#include <future> 
#include <functional> 
#include <thread> 

template <typename T> 
class MyPackagedTask : public std::packaged_task<T()> { 
    public: 
    template <typename F> 
    explicit MyPackagedTask(F&& f) 
     : std::packaged_task<T()>(std::forward<F>(f)) {} 

    MyPackagedTask(MyPackagedTask&& other) 
     : std::packaged_task<T()>(std::move(other)) {} 

    MyPackagedTask(const MyPackagedTask& other) { 
     // Adding this borks the compile 
    } 
}; 

int main() 
{ 
    MyPackagedTask<int> task([]() {return 0;}); 
    auto future = task.get_future(); 
    std::thread t(std::move(task)); 
    t.join(); 

    std::cout << future.get() << std::endl; 
} 

私は、次のエラーメッセージ(ちょうど端部が、...あなたは全部を望むなら、私に知らせて)取得:

/usr/include/c++/6.2.1/future:1325:6: error: invalid use of void expression 
     (*_M_result)->_M_set((*_M_fn)()); 

エラーメッセージ私には分かりませんでしたので、何か間違っているのか、コンパイラが失敗しているのか不思議でした。

+4

なぜBjarne Stroustrupの名前であなたは 'std :: packaged_task'から継承していますか?あなたは最高にそれを構成してはいけませんか? 'std :: packaged_task'は何かを生成することを約束するリソースです。あなたは[Yakkの仕事](https://stackoverflow.com/documentation/c%2b%2b/2872/type-erasure/18042/a)を見たいかもしれません。 -move-only-stdfunction) – WhiZTiM

+0

質問で述べたように、私はstd :: functionのコピーコンストラクタの必要条件を回避したいと思います。合成すると、 'std :: packaged_task'のすべての機能のためのラッパーを提供する必要があり、遭遇しているバグを取り除くことはできません。 –

+0

理由:std ::関数の形式でタスクをポストできるスレッドキューがあります。 void以外の関数をpackaged_taskにラップし、そのキューにあるものをplopし、その結果を得るためにpackaged_taskの将来を使用したいとします。 –

答えて

1

移動コンストラクタの定義が正しくない場合は、std::packaged_task<T()>&&MyPackagedTask&&と転送し、間違ったコンストラクタをstd::packaged_task<T()>として呼び出します。これはあなたが観察するコンパイラエラーの原因です。

正しい

MyPackagedTask(MyPackagedTask&& other) 
    : std::packaged_task<T()>(static_cast<std::packaged_task<T()>&&>(other)) 
{} 
static_cast<std::packaged_task<T()>&&>(other)

そこでは、基本クラスとstd::moveにアップキャストの両方を行います。

+0

ありがとう、マキシム。 –

+1

型安全性をさらに高めるために、 'std :: move >(other)'と書くことができますか? (それはダウンキャストを許さないだろうが、アップキャストのみ)。 –

+0

@TobySpeightそれはうまくいくでしょう。まったく同じことになります –

関連する問題