2012-04-20 6 views
5

私は基本的に次のコードを持っている:のInvokeのstd ::機能:: for_each

typedef std::function<void()> fnGlobalChangeEvent; 
typedef std::vector<fnGlobalChangeEvent> GlobalTriggers; 

inline void ExecuteGlobal(fnGlobalChangeEvent ev) 
{ 
    ev(); 
} 

GlobalTriggers triggers; 
std::for_each(triggers.begin(), triggers.end(), std::bind(&ExecuteGlobal, _1)); 

がExecuteGlobalの使用は、ここで完全に冗長な感じを、私はドロップアウトする権利構文を見つけることができません呼び出し。

std::for_each(triggers.begin(), triggers.end(), ExecuteGlobal(_1)); 
std::for_each(triggers.begin(), triggers.end(), std::bind(_1)); 

どちらもコンパイルできません。

より複雑な場合もあります:

typedef std::function<void (Zot&)> fnChangeEvent; 
typedef std::vector<fnChangeEvent> Triggers; 

inline void Execute(fnChangeEvent ev, Zot& zot) 
{ 
    ev(zot); 
} 

Triggers triggers; 
std::for_each(triggers.begin(), triggers.end(), std::bind(&Execute, _1, zot)); 

それはこれらのケースではヘルパー関数なしで行うことは可能ですか?

+2

最新のC++標準(C++ 11)の新しい 'for'構文を見てみるといいでしょう:http://en.wikipedia.org/wiki/C%2B%2B11#Range -based_for-loop – lvella

+4

最初の例では、冗長なのは、std :: bindを使用することです:std :: for_each(triggers.begin()、triggers.end()、ExecuteGlobal); ' –

+0

@ benjamin-lindley :ありがとう、私はより複雑なケースから戻ってきて、余分な冗長性を欠いていた! –

答えて

7

確かに、ラムダ:

あなたのようにラムダを使用していないのはなぜ
for (auto ev : triggers) { 
    ev(); 
} 

// well, I think you can figure out the second one 
+0

ラムダは動作しますが、イテレータ変数として既に有効な機能を持っていたので、新しいラッパーを作成することなく直接使用する方法があるはずです。 –

+1

@RobWalker:これも可能ですが、Boostを使用する必要があります。それを使用できますか? – Nawaz

+0

実際には、最新のC++標準(2011)のものなので、最近のコンパイラが必要になります。 – lvella

4

std::for_each(triggers.begin(), 
       triggers.end(), 
       [&](fnChangeEvent & e) 
       { 
        e(zot); 
       }); 

またはレンジ・利用するための

std::for_each(
    triggers.begin(), triggers.end(), 
    [](fnChangeEvent ev) { ev(); } 
); 
std::for_each(
    triggers.begin(), triggers.end(), 
    [&zot](fnChangeEvent ev) { ev(zot); } 
); 

あるいはさらに良い、範囲forループとして:

for (auto& e : triggers) { e(zot); } 

もっと簡潔できれいに見えます。

1

ここで私はちょうど思っ何か、それはあなたが探しているもののようなものだなら、私に教えてくれます:

call_each(triggers.begin(), triggers.end()); 

そして持つ機能について:

template<typename IT, typename ...Args> 
void call_each(IT begin_, IT end_, Args&&... args) 
{ 
    for (auto i = begin_; i!=end_; ++i) 
     (*i)(std::forward<Args>(args)...); 
} 

その後、あなたはこのようにそれを使用することができますが、引数:

call_each(triggers.begin(), triggers.end(), zot); 
+1

悪い考え。関数テンプレート 'std :: forward'を間違った方法で使用しています。 rvalueが 'call_each'に渡されると、_object_は最初の反復で移動され、他の反復は間違った_object_を使用します。 – nosid

0

だけで、私はそのオプションを忘れないだろう。

関連する問題