2017-08-29 23 views
2

私はこのようなキューにそれらを結合することにより、スケジュール機能クラスに取り組んでいる:あなたは、私はそれが関数オブジェクトの任意の型を保持するためにqueuevoid()タイプを作ったが、今見たよう標準ライブラリでstd :: bindを使用して戻り値の型を保存する方法

std::queue <void()> q; 

template<typename R,typename... ArgsT> 
     void 
     schedule(R& fn, ArgsT&... args) 
     { 
      q.push(std::bind(fn, std::forward<ArgsT>(args)...)); 
     }; 

template<typename R,typename... ArgsT> 
     void 
     schedule(R&& fn, ArgsT&&... args) 
     { 
      q.push(std::bind(fn, std::forward<ArgsT>(args)...)); 
     }; 

私はそれを実行するときに私はリターンを得ることができません。これを解決するにはどうすればよいですか?

注:私はboostのような外部ライブラリを使いたくないので、ユーザーがどのような機能を渡すか分かりません。

+7

タイプがわからない場合は、何を返すかと思いますか? – Kevin

+0

C++ 17や 'boost :: any'に' std :: any'があります。しかし、あなたはどちらかを使いたくないようです。 – Rakete1111

+0

@Kevinこれはクラスのクラスの一部であり、キューの中の関数をスケジュールし、それらを同時に実行すると、ユーザーは関数の実行後に戻り値を得ることができるので、std :: futureで取得するためにいくつかの方法を保存したいユーザーに –

答えて

3

注:私はboostのような外部ライブラリを使いたくないのですが、私は がユーザーに渡す機能の種類を知っていません。

私は通常、この場合、私はキュー内の基本クラス(コマンドパターンから)を使用して、2つの実装、1つはバインドをラップし、もう1つは(バインドをラッピングする)戻り値を取得できる関数です。ここで

が(最後に)戻って専門の例である:

#include <iostream> 
#include <functional> 
#include <memory> 


struct ACmd 
{ 
    virtual void exec() = 0; 
    virtual ~ACmd(){} 
}; 

template <class F> 
struct Cmd; 

template <class R, class ... Args> 
struct Cmd<R(Args...)> : ACmd 
{ 
    R result_; 
    std::function<R()> func_; 

    template <class F> 
    Cmd(F&& func, Args&&... args): result_(), func_() 
    { 
    auto f = std::bind(std::forward<F>(func), std::forward<Args>(args)...); 
    func_ = [f](){ 
     return f(); 
    }; 
    } 

    virtual void exec(){ 
    result_ = func_(); 
    } 

    const R& getResult() const {return result_;} 
}; 

// Make function for convenience, could return by value or ptr - 
// - your choice 
template <class R, class F, class ...Args> 
Cmd<R(Args...)>* cmd(F&& func, Args&&... args) 
{ 
    return new Cmd<R(Args...)>(func, std::forward<Args>(args)...); 
} 

//... And overload for void... 

int foo(int arg) { 
    return arg; 
} 

int main() { 

    auto x = cmd<int>(foo, 10); 
    x->exec(); 
    std::cout << x->getResult() << std::endl; 
    return 0; 
} 
1

queue内の各要素の実行の結果、それはあなたがすでにそのように定義されている、voidです。渡された関数が値を返す必要がある場合は、返される型を固定型に制限する必要があります。std::any,std::variantなどのユーティリティやいくつかの共変タイプ(std::unique_ptrまたはstd::shared_ptrで可能)を使用する必要があります。

最も簡単なのは、(コンパイル時に)戻り値の型を修正することです。

template <typename R> 
using MQ = std::queue<std::function<R()>>; 

MQ<int> q; 

以下のサンプルを参照してください。


キュー宣言は、std::functionオブジェクトなどのオブジェクトのqueueする必要があります。 bindの戻り値はfunctionに割り当てられ、次に期待どおりに使用されます。

std::functionは多形関数ラッパーで、anyに類似した型消去パターンを実装しますが、関数やその他の呼び出し可能オブジェクト用に特別に設計されています。

example;

template <typename R> 
using MQ = std::queue<std::function<R()>>; 

MQ<int> q; 

template<typename R,typename... ArgsT> 
     void 
     schedule(R&& fn, ArgsT&&... args) 
     { 
      q.push(std::bind(std::forward<R>(fn), std::forward<ArgsT>(args)...)); 
     }; 

int main() 
{ 
    schedule([](int a) { std::cout << "function called" << std::endl; return a; }, 42); 

    std::cout << q.front()() << std::endl; 
} 
関連する問題