2017-10-09 8 views
0

私は、クラスメソッドに任意の数のコールバック関数を持ち、すべてを実行してから出力を格納する方法を考えようとしています。私はこれがうまくいくと思いますが、ユーザーがベクターにすべてのコールバック関数をラップさせる必要がないところで、これを行う方法がありますか?これはちょうど乱雑に感じる。理想的ではないことを言いたいことは自由です。任意の数のコールバックを取り、結果を格納するC++クラスのメソッド

#include <iostream> 
#include <functional> 
#include <vector> 

class MyObj{ 
public: 
    // where I store stuff 
    std::vector<double> myResults; 

    // function that is called intermittently 
    void runFuncs(const std::vector<std::function<double()> >& fs){ 
     if (myResults.size() == 0){ 
      for(auto& f : fs){ 
       myResults.push_back(f()); 
      } 
     }else{ 
      int i (0); 
      for(auto& f : fs){ 
       myResults[i] = f(); 
       i++; 
      } 
     } 
    } 

}; 


int main(int argc, char **argv) 
{ 

    auto lambda1 = [](){ return 1.0;}; 
    auto lambda2 = [](){ return 2.0;}; 

    MyObj myThing; 

    std::vector<std::function<double()> > funcs; 
    funcs.push_back(lambda1); 
    funcs.push_back(lambda2); 
    myThing.runFuncs(funcs); 

    std::cout << myThing.myResults[0] << "\n"; 
    std::cout << myThing.myResults[1] << "\n"; 

    std::vector<std::function<double()> > funcs2; 
    funcs2.push_back(lambda2); 
    funcs2.push_back(lambda1); 
    myThing.runFuncs(funcs2); 

    std::cout << myThing.myResults[0] << "\n"; 
    std::cout << myThing.myResults[1] << "\n"; 


    return 0; 
} 
+0

としてそれを呼び出すことができますコールバックは最初のコールバックより2回目ですか?現時点では、プログラムはこの場合未定義の動作を示します。 –

+0

私は '.empty()'を使ってベクトルが空であるかどうかを判断しますが、コールバックの数に合わせてサイズを変更し、結果をforループに代入するほうが良いでしょう。ベクトルが空でない場合は正しいサイズであることがわかります。 –

+1

これは私にとって少し清潔に思えます。 * shrug * https://ideone.com/WN697O –

答えて

1

おそらくこのような何か、:

template <typename... Fs> 
void runFuncs(Fs... fs) { 
    myResults = std::vector<double>({fs()...}); 
} 

次に、あなたは

`runFuncs`がよりを渡し、2回呼び出された場合にどうするか
myThing.runFuncs(lambda1, lambda2); 

Demo

+0

これはクールに見える。それは可変的なテンプレートですよね? '{fs()...}'の部分はどうなっていますか?私はそれがちょうどすべての機能を呼び出すと思いますが、これは何と呼ばれていますか?なぜ中括弧で囲む必要がありますか? – Taylor

+1

[パラメータパックの展開](http://en.cppreference.com/w/cpp/language/parameter_pack#Pack_expansion)をブレース初期リストに追加します。これは、 'std :: vector ({1.0、2.0、3.0})'のように、 'initializer_list'を取って' vector'のコンストラクタを呼び出しています。拡張自体は中括弧で囲む必要はありません。それらはパック展開構文ではなく、イニシャライザリストの構文の一部です。 –

関連する問題