forループよりもstd :: for_eachの利点


166

std::for_eachオーバーforループの利点はありますか?私には、std::for_eachコードの可読性を妨げるだけのようです。では、なぜいくつかのコーディング標準がその使用を推奨しているのですか?


10
std::for_eachと併用した場合、boost.lambdaまたはboost.bind読みやすさを向上できることが多い

質問と承認された回答は2010年のものです。より最新の回答(2018年から)については、こちらを参照してください:fluentcpp.com/2018/03/30/is-stdfor_each-obsolete
Segal-Halevi

回答:


181

C ++ 11(以前はC ++ 0xと呼ばれていました)のいいところは、この面倒な議論が解決されることです。

つまり、コレクション全体を反復処理したいという正しい考えの誰も、これを使用しません

for(auto it = collection.begin(); it != collection.end() ; ++it)
{
   foo(*it);
}

またはこれ

for_each(collection.begin(), collection.end(), [](Element& e)
{
   foo(e);
});

とき範囲ベースのforループ構文を使用できます。

for(Element& e : collection)
{
   foo(e);
}

この種の構文は、しばらくの間JavaとC#で利用可能であり、実際、最近のすべてのJavaまたはC#コードにはforeach、従来のforループよりもはるかに多くのループがあります。


12
実際、スクープを使用したforeachループはboostで長い間利用可能でしたが、私はまだfor_eachとラムダ関数で繰り返し処理したいと思っています。
Viktor Sehr

19
コンテナー範囲全体が必要であるという仮定は問題の一部ではないため、これは部分的な答えにすぎません。
Adrian McCarthy

6
要素をループすることはおそらくあなたがしたいことだけではないことに注意してください、それでfor / eachを使用するのは良い考えです。行う。
マッケ

10
イテレータが実際に必要な場合を除いて、range-forは便利です(その場合、イテレータに到達する方法はありません)。
デイモン

5
私も使っていないのだElement & eauto & e(あるいはauto const &e良く見えます)。Element const e暗黙的な変換が必要な場合、たとえばソースがさまざまなタイプのコレクションであり、それらをに変換したい場合は(参照なしで)使用しElementます。
Nawaz

53

ここにいくつかの理由があります:

  1. 慣れていなかったり、周りに適切なツールを使用していないために、読みやすさが妨げられているようです。(ヘルパーについては、boost :: rangeおよびboost :: bind / boost :: lambdaを参照してください。これらの多くはC ++ 0xに入り、for_eachおよび関連する関数がより便利になります。)

  2. これにより、任意のイテレーターで機能するアルゴリズムをfor_eachの上に記述できます。

  3. それは愚かなタイピングのバグの可能性を減らします。

  4. それはまたのような、STL-アルゴリズムの残りの部分にあなたの心を開きfind_ifsortreplaceなど、これらはもうそれほど奇妙に見えることはありません。これは大きな勝利になる可能性があります。

更新1:

最も重要なのは、それだけでなくfor_eachforループを超えて、find / sort / partition / copy_replace_if、並列実行などの他のSTLアナログを確認するのに役立ちます。

多くの処理は、for_eachの兄弟の「残りの部分」を使用して非常に簡潔に記述できますが、さまざまな内部ロジックを使用してforループを記述するだけであれば、それらの使用方法を学ぶことはできません。ホイールを何度も発明することになります。

そして(間もなく利用可能になる範囲スタイルのfor_each):

for_each(monsters, boost::mem_fn(&Monster::think));

またはC ++ x11ラムダ:

for_each(monsters, [](Monster& m) { m.think(); });

IMOは次のものより読みやすいです:

for(Monsters::iterator i = monsters.begin(); i != monsters.end(); ++i) {
    i->think();
} 

これも(またはラムダを使用して、他の人を参照):

for_each(bananas, boost::bind(&Monkey::eat, my_monkey, _1));

より簡潔です:

for(Bananas::iterator i = bananas.begin(); i != bananas.end(); ++i) {
    my_monkey->eat(*i);
} 

特に、順番に呼び出す関数がいくつかある場合は...たぶんそれは私だけです。;)

更新2:イテレータのペアの代わりに範囲で機能するstl-algosの独自の1行ラッパーを作成しました。boost :: range_ex、一度リリースされると、それが含まれ、おそらくC ++ 0xにも存在するでしょうか?


1、いくつかの機能またはネストされたタイプ:outer_class::inner_class::iteratorまたは彼らはテンプレート引数です:typename std::vector<T>::iterator...自体は、それ自体に多くのライン構築物に実行することができます構築物について
デビッド・ロドリゲス- dribeas

4
(ところで:for_each第二の例では、正しくない(する必要がありますfor_each( bananas.begin(), bananas.end(),...
デビッド・ロドリゲス- dribeas

2つのイテレータの代わりに範囲を使用するラッパーを作成しました。これらは後で利用可能になります(range_exを参照)。(その上で更新を追加。)
Macke

1
並列処理のサポートはありません。ここに1つの理由があります。異種並列コンピューティングにcuda / gpuを使用する実装を追加できます。
shuva

24

for_eachより一般的です。これを使用して、任意のタイプのコンテナーを反復できます(開始/終了反復子を渡すことにより)。潜在的にfor_each、反復コードを更新せずにを使用する関数の下のコンテナーを交換できます。std::vectorの利点を確認するには、世界中にプレーンな古いC配列以外のコンテナがあることを考慮する必要がありますfor_each

の主な欠点for_eachは、ファンクタが必要になるため、構文が不格好です。これはラムダの導入によりC ++ 11(以前のC ++ 0x)で修正されています。

std::vector<int> container;
...
std::for_each(container.begin(), container.end(), [](int& i){
    i+= 10;
});

これは3年間であなたにとって奇妙に見えなくなります。


3
+1。for_eachが2つのイテレータではなくコンテナ/範囲を取る場合の広告は、これまで以上に優れています。
Macke

2
@Marcus:遠隔-のためになります構築物および構文自体に「for_each」を読んでいないだろう。for ( int v : int_vector ) {(それはBOOST_FOREACHで今日シミュレートすることができたとしても)
デビッド・ロドリゲス- dribeas

@デビッド:私は、(あなたは、これらすべてのfor_eachと範囲を使用することができますので、コピー、remove_if、などなどの機能)範囲ベースの機能の一般的な追加を参照しています
マッケ

1
なぜ書き込めないのですか:std::for_each(container, [](int& i){ ... });。つまり、なぜコンテナを2回記述する必要があるのでしょうか。
Giorgio

1
@freitass:以前のコメントのようにコンテナを一度書き込むと、明示的に呼び出さずにbegin endイテレータをデフォルトで使用できます。コレクションに高階関数を提供するほとんどの言語(Ruby、Scalaなど)は、container.each { ... }開始反復子と終了反復子について言及せずに、次のようなものを記述します。常に終了イテレータを指定する必要があるのは少し冗長だと思います。
ジョルジオ

17

個人的に、私が使用する方法から外れる必要があるときはいつでもstd::for_each(特別な目的のファンクタ/複雑なboost::lambdasを書く)、BOOST_FOREACHC ++ 0xの範囲ベースを見つけて明確にします:

BOOST_FOREACH(Monster* m, monsters) {
     if (m->has_plan()) 
         m->act();
}

std::for_each(monsters.begin(), monsters.end(), 
  if_then(bind(&Monster::has_plan, _1), 
    bind(&Monster::act, _1)));

11

その非常に主観的なもので、同じ規則で異なるコレクションを扱うことができるfor_each ので、使用するとコード読みやすくなると言う人もいます。 for_eachitslefはループとして実装されます

template<class InputIterator, class Function>
  Function for_each(InputIterator first, InputIterator last, Function f)
  {
    for ( ; first!=last; ++first ) f(*first);
    return f;
  }

ですから、あなたに合ったものを選ぶのはあなた次第です。


11

アルゴリズム関数の多くと同様に、最初の反応は、ループよりもforeachを使用する方が読みにくいと考えることです。それは多くの炎上戦争のトピックでした。

あなたが慣用句に慣れると、あなたはそれが役に立つかもしれません。明らかな利点の1つは、コーダーにループの内部コンテンツを実際の反復機能から分離させることです。(わかりました、私はそれが利点だと思います。他の人はあなたが本当の利益なしにコードを切り刻んでいると言います)。

もう一つの利点は、私はforeachのを見たときに、私がいることである知っているすべてのアイテムのいずれかが処理されるか、例外がスローされますことを。

A のためのループは、ループを終了するためのいくつかのオプションを使用できます。ループを完全に実行させるか、breakキーワードを使用して明示的にループからジャンプするか、returnキーワードを使用してループ全体の関数を終了できます。対照的に、foreachはこれらのオプションを許可しないため、読みやすくなります。関数名を見るだけで、反復の完全な性質を知ることができます。

これは、紛らわしいforループの例です。

for(std::vector<widget>::iterator i = v.begin(); i != v.end(); ++i)
{
   /////////////////////////////////////////////////////////////////////
   // Imagine a page of code here by programmers who don't refactor
   ///////////////////////////////////////////////////////////////////////
   if(widget->Cost < calculatedAmountSofar)
   {
        break;
   }
   ////////////////////////////////////////////////////////////////////////
   // And then some more code added by a stressed out juniour developer
   // *#&$*)#$&#(#)$#(*$&#(&*^$#(*$#)($*#(&$^#($*&#)$(#&*$&#*$#*)$(#*
   /////////////////////////////////////////////////////////////////////////
   for(std::vector<widgetPart>::iterator ip = widget.GetParts().begin(); ip != widget.GetParts().end(); ++ip)
   {
      if(ip->IsBroken())
      {
         return false;
      }
   }
}

1
あなたは良い点を述べますが、あなたの動機の例は完全に公平ではありません。あなたが使用している場合std::for_each()(つまり、この記事の時点で)、旧規格では、あなたが言うように、読みやすさを奨励し、途中でループを抜け出し禁止という名前のファンクタを使用する必要があります。しかし、同等のforループには関数呼び出ししかなく、それも早すぎるブレークアウトを禁止します。しかし、それ以外は、範囲全体をstd::for_each() 強制することを言った点で優れていると思います。
ヴィルヘルムテル

10

あなたはほとんど正しいです:ほとんどの場合std::for_each、純損失です。と比較for_eachするまで私は行きgotoます。gotoは、最も用途の広いフロー制御を提供します。これを使用して、想像できる他のあらゆる制御構造を事実上実装できます。ただし、その非常に汎用性があるということはgoto、単独でinを表示しても、この状況で何をしようとしているのかについてほとんど何も知らないことを意味します。その結果、goto最後の手段として使用する場合を除いて、右心の誰も使用しません。

標準的なアルゴリズムの中で、これfor_eachはほとんど同じ方法です-事実上すべてを実装するために使用できます。つまりfor_each、この状況で何が使用されているかを確認しても、事実上何もわかりません。残念ながら、人々の態度for_eachgoto(たとえば)1970 年頃の態度に関するものです- 一部の人々は、それが最後の手段としてのみ使用されるべきであるという事実に気づきましたが、多くの人は依然としてそれを主要なアルゴリズムと考えています、そして他のものを使用することはめったにありません。ほとんどの場合、一目見ただけでも、代替案の1つが大幅に優れていることがわかります。

たとえば、人々がを使用してコレクションの内容を出力するためのコードを書いているのを見たことが何回あったのか、私はかなり確信を失っていfor_eachます。私が見た投稿によると、これはの最も一般的な使用法の1つですfor_each。彼らは次のようなものになります:

class XXX { 
// ...
public:
     std::ostream &print(std::ostream &os) { return os << "my data\n"; }
};

そして、彼らのポストには、どのような組み合わせについて尋ねているbind1stmem_funなど彼らは同じような何かを行う必要があります。

std::vector<XXX> coll;

std::for_each(coll.begin(), coll.end(), XXX::print);

作業し、の要素を出力しcollます。私がそこで書いたとおりに実際に機能した場合、それは平凡なものになりますが、機能しません-機能するようになるまでに、一緒にそれを保持する部分の間で起こっています。

幸い、もっと良い方法があります。XXXの通常のストリームインサーターオーバーロードを追加します。

std::ostream &operator<<(std::ostream *os, XXX const &x) { 
   return x.print(os);
}

と使用std::copy

std::copy(coll.begin(), coll.end(), std::ostream_iterator<XXX>(std::cout, "\n"));

それは仕事をして-そしてそれは内容印刷していることを把握するために、すべてのほとんどの仕事を取らないcollのをstd::cout


+1、1つ間違いがあります。最初の例では、次のようにすべきでboost::mem_fn(&XXX::print)はありませんXXX::print
missingfaktor

だから私はその例がうまくいかないと私が言った、そして彼らはそれを機能させるために助けを求めて投稿している(ああ、そしてstd::coutそれが機能するための引数としてバインドする必要もある)。
Jerry Coffin、2010年

1
一般的には良い答えですが、問題はfor_eachの値や他のstdアルゴリズムと比較した値ではなく、forループと比較した値です。他のstdアルゴリズムが適用されない場合にそれを考えるかもしれません。次に、for_eachまたはforループを使用しますか?それについて考え、あなたが思いつくものは何でも、それはあなたの答えであったはずです。
Christian Rau

@ChristianRau:質問どおりに質問に答えることと、役立つ情報を提供しようとすることの間には、常に微妙な違いがあります。彼が尋ねた質問に対する正確な直接の答えは「おそらくない。だれが知っているか」であろうが、面倒に値するほど役に立たないでしょう。同時に、あまりにも遠く(たとえば、上記のいずれかではなくHaskellを推奨すること)もあまり役に立ちません。
Jerry Coffin、

3
@ChristianRau:「...ほとんどの場合、std :: for_eachは純損失」がstd :: for_eachが利点を提供するかどうかの問題に対処していないことをどのように理解しますか?
ジェリーコフィン

8

ときに、より読みやすいbeeingてのための機能の書き込みの利点は、表示されないことがありますfor(...)for_each(...)。

forループを使用する代わりに、functional.hですべてのアルゴリズムを利用する場合、コードはより読みやすくなります。

iterator longest_tree = std::max_element(forest.begin(), forest.end(), ...);
iterator first_leaf_tree = std::find_if(forest.begin(), forest.end(), ...);
std::transform(forest.begin(), forest.end(), firewood.begin(), ...);
std::for_each(forest.begin(), forest.end(), make_plywood);

あるずっと読みやすく超えます。

Forest::iterator longest_tree = it.begin();
for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
   if (*it > *longest_tree) {
     longest_tree = it;
   }
}

Forest::iterator leaf_tree = it.begin();
for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
   if (it->type() == LEAF_TREE) {
     leaf_tree  = it;
     break;
   }
}

for (Forest::const_iterator it = forest.begin(), jt = firewood.begin(); 
     it != forest.end(); 
     it++, jt++) {
          *jt = boost::transformtowood(*it);
    }

for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
    std::makeplywood(*it);
}

そして、それは私がとても良いと思うものです、forループを1行の関数に一般化します=)


6

簡単:for_eachすでにすべての配列項目を処理する関数があるため、ラムダを記述する必要がない場合に便利です。確かに、これ

for_each(a.begin(), a.end(), a_item_handler);

よりも良い

for(auto& item: a) {
    a_item_handler(a);
}

また、遠隔forループは、コンテナ全体を最初から最後まで反復するだけfor_eachですが、より柔軟です。


4

for_eachループは、操作上の明確なセマンティクスをユーザコードからイテレータ(ループの実装方法の詳細)を非表示と定義することを意味する:各要素は、一度だけ繰り返されます。

現在の標準の可読性の問題は、コードのブロックの代わりに最後の引数としてファンクターを必要とすることです。そのため、多くの場合、特定のファンクタータイプを記述する必要があります。ファンクターオブジェクトはインプレースで定義できず(関数内で定義されたローカルクラスはテンプレート引数として使用できません)、ループの実装を実際のループから移動する必要があるため、これは可読性の低いコードになります。

struct myfunctor {
   void operator()( int arg1 ) { code }
};
void apply( std::vector<int> const & v ) {
   // code
   std::for_each( v.begin(), v.end(), myfunctor() );
   // more code
}

あなたは、各オブジェクトに対して特定の操作を実行したい場合は、あなたが使用できることに注意してくださいstd::mem_fn、またはboost::bindstd::bind次の標準で)、またはboost::lambdaそれを簡単にするために(次の標準でラムダ):

void function( int value );
void apply( std::vector<X> const & v ) {
   // code
   std::for_each( v.begin(), v.end(), boost::bind( function, _1 ) );
   // code
}

これは、適切な場所で呼び出す関数/メソッドがある場合、手動バージョンよりも読みやすく、コンパクトではありません。実装は、for_eachループの他の実装を提供することができます(並列処理と考えてください)。

次の標準では、いくつかの欠点をさまざまな方法で処理します。ローカルに定義されたクラスをテンプレートの引数として使用できます。

void apply( std::vector<int> const & v ) {
   // code
   struct myfunctor {
      void operator()( int ) { code }
   };
   std::for_each( v.begin(), v.end(), myfunctor() );
   // code
}

コードの局所性の向上:ブラウズすると、コードの動作がすぐにわかります。実際のところ、ファンクタを定義するためにクラス構文を使用する必要さえありませんが、その場でラムダを使用します。

void apply( std::vector<int> const & v ) {
   // code
   std::for_each( v.begin(), v.end(), 
      []( int ) { // code } );
   // code
}

for_eachより自然にする特定の構成がある場合でも、

void apply( std::vector<int> const & v ) {
   // code
   for ( int i : v ) {
      // code
   }
   // code
}

for_each手巻きのループと構造を混ぜる傾向があります。既存の関数またはメソッドへの呼び出しだけが必要な場合(for_each( v.begin(), v.end(), boost::bind( &Type::update, _1 ) )for_each、コードからボイラープレートイテレーターに関する多くの要素を取り除いた構造体を使用します。もっと複雑なものが必要で、実際の使用の数行上にファンクターを実装できない場合は、独自のループをロールします(操作を適切に維持します)。コードの重要ではないセクションでは、BOOST_FOREACHを使用する可能性があります(同僚に教えてもらった)


3

可読性とパフォーマンスの他に、一般的に見落とされる側面の1つは一貫性です。for(またはwhile)ループを反復子に実装する方法はたくさんあります。

for (C::iterator iter = c.begin(); iter != c.end(); iter++) {
    do_something(*iter);
}

に:

C::iterator iter = c.begin();
C::iterator end = c.end();
while (iter != end) {
    do_something(*iter);
    ++iter;
}

さまざまなレベルの効率とバグの可能性の中間に多くの例があります。

ただし、for_eachを使用すると、ループが抽象化され、一貫性が強化されます。

for_each(c.begin(), c.end(), do_something);

今気にしなければならない唯一のことは、BoostまたはC ++ 0x機能を使用して、関数、ファンクター、またはラムダとしてループ本体を実装することですか?個人的には、ランダムなfor / whileループを実装または読み取る方法よりも、それについて心配したいと思います。


3

私は以前は嫌いでstd::for_each、ラムダなしでは、それは完全に間違って行われたと思っていました。しかし、私は少し前に考えを変えました、そして今、私は実際にそれを愛しています。読みやすさも向上し、TDDの方法でコードを簡単にテストできるようになると思います。

std::for_eachアルゴリズムは次のように読み取ることができる範囲内のすべての要素を持つ何かでき可読性を向上させます。実行したいアクションが20行で、アクションが実行される機能も20行程度だとします。これにより、従来のforループでは関数が40行長くなり、で約20行になるため、std::for_each理解しやすくなります。

のファンクタはstd::for_eachより一般的であり、したがって再利用可能である可能性が高くなります。例:

struct DeleteElement
{
    template <typename T>
    void operator()(const T *ptr)
    {
        delete ptr;
    }
};

そして、コードにstd::for_each(v.begin(), v.end(), DeleteElement())は、明示的なループよりもわずかに優れたIMOのような1行しかありません。

これらの関数はすべて、通常、長い関数の途中で明示的なforループを実行するよりも単体テストを実施する方が簡単です。それだけでも、すでに大きなメリットがあります。

std::for_each また、範囲を間違える可能性が少ないため、一般に信頼性が高くなります。

そして最後に、コンパイラーはstd::for_each、特定の種類の手作りのforループよりもわずかに優れたコードを生成する可能性があります。これは、for_each がコンパイラーに対して常に同じに見えるため、コンパイラー作成者は知識をすべて入れて、それと同じようにすることができますできる。

同じことは、のような他のSTDのアルゴリズムに適用されるfind_iftransformなど


2

for各要素を繰り返すことができるforループまたは3つおきなどfor_eachは、各要素のみを繰り返すためのものです。その名前から明らかです。そのため、コードで何をしようとしているのかがより明確になります。


4
あなたがそれにそれを渡すなら、それぞれで3ずつ進むイテレータではありません++。珍しいかもしれませんが、forループも同じです。
Potatoswatter、2010年

その場合、多分transform誰かを混乱させないために使う方が良いでしょう。
キリルV.リャドビンスキー2010年

2

STLの他のアルゴリズムを頻繁に使用する場合、いくつかの利点がありますfor_each

  1. これは多くの場合、forループよりも単純で、エラーが発生しにくくなります。これは、一部はこのインターフェイスの機能に慣れているため、一部は実際には多くの場合少し簡潔であるためです。
  2. 範囲ベースのforループはさらに単純になる可能性がありますが、柔軟性は低くなります(Adrian McCarthyが指摘したように、コンテナー全体で反復します)。
  3. 従来のforループとは異なり、for_each任意の入力反復子で機能するコードを作成する必要があります。このように制限されていることは、実際には良いことです。

    1. 実際には、後で別のコンテナーで機能するようにコードを調整する必要がある場合があります。
    2. 初めに、それはあなたに何かを教えたり、あなたの習慣をより良いものに変えるかもしれません。
    3. 常に完全に等価なforループを作成する場合でも、同じコードを変更する他の人は、を使用するように求められることなくこれを行わない可能性がありますfor_each
  4. 使用for_eachすると、より具体的なSTL関数を使用して同じことを実行できることが明らかになります。(Jerry Coffinの例のように、必ずしもそうであるfor_eachとは限りませんが、forループが唯一の選択肢ではありません。)


2

C ++ 11と2つの単純なテンプレートを使用すると、次のように記述できます。

        for ( auto x: range(v1+4,v1+6) ) {
                x*=2;
                cout<< x <<' ';
        }

for_eachまたはループの代わりとして。なぜそれを簡潔さと安全性に要約するのかを選択する理由は、そこにない式でエラーが発生する可能性がないということです。

私にとって、for_eachループボディが既にファンクタである場合、同じ理由で常に優れていました。そして、私が得ることができるあらゆる利点を活用します。

まだ3つの式を使用していforますが、ここで何かを理解していることがわかった場合、それは定型ではありません。私は嫌い定型を。私はその存在に憤慨しています。それは本当のコードではありません、それを読むことによって学ぶことは何もありません、それはチェックを必要とするもう一つだけのものです。精神的な努力は、それをチェックするときに錆びやすくなることがどれだけ簡単かによって測定できます。

テンプレートは

template<typename iter>
struct range_ { 
                iter begin() {return __beg;}    iter end(){return __end;}
            range_(iter const&beg,iter const&end) : __beg(beg),__end(end) {}
            iter __beg, __end;
};

template<typename iter>
range_<iter> range(iter const &begin, iter const &end)
    { return range_<iter>(begin,end); }

1

ほとんどの場合、コレクション全体反復処理する必要があります。したがって、2つのパラメーターのみを使用して独自のfor_each()バリアントを作成することをお勧めします。これにより、Terry Mahaffeyの例を次のように書き換えることができます。

for_each(container, [](int& i) {
    i += 10;
});

これは確かにforループよりも読みやすいと思います。ただし、これにはC ++ 0xコンパイラー拡張機能が必要です。


1

for_eachは可読性が悪いと思います。コンセプトは良いものですが、c ++では、少なくとも私にとって、読みやすく書くことは非常に困難です。c ++ 0xラムダ式が役立ちます。私はラムダのアイデアが本当に好きです。しかし、一見すると、構文は非常に醜いと思いますし、これに慣れるかどうかは100%わかりません。たぶん5年後には慣れてきて、二度と考えなかったかもしれませんが、そうではないかもしれません。時が教えてくれる :)

使いたい

vector<thing>::iterator istart = container.begin();
vector<thing>::iterator iend = container.end();
for(vector<thing>::iterator i = istart; i != iend; ++i) {
  // Do stuff
}

明示的なforループの読み取りが明確になり、開始および終了反復子に名前付き変数を明示的に使用すると、forループの乱雑さが軽減されます。

もちろん、ケースはさまざまですが、これが私が通常最もよく見つけるものです。


0

イテレータを、ループの各反復で実行される関数の呼び出しにすることができます。

ここを参照してください:http : //www.cplusplus.com/reference/algorithm/for_each/


2
リンクのみの投稿は良い答えを出しません。とにかく、そのリンクのどこに、呼び出し可能なイテレータに似ているものが表示されますか?私はその概念が意味をなさないだけだと確信しています。たぶん、あなたは何をするのかを要約しているだけかもしれfor_eachません。その場合、それはその利点についての質問に答えません。
underscore_d


0

for_eachFork-Joinパターンを実装できるようにします。それ以外はfluent-interfaceをサポートしています

フォーク結合パターン

gpu::for_each複数のワーカーでラムダタスクを呼び出すことにより、異機種並列コンピューティングにcuda / gpuを使用する実装を追加できます。

gpu::for_each(users.begin(),users.end(),update_summary);
// all summary is complete now
// go access the user-summary here.

そしてgpu::for_each、次のステートメントを実行する前に、ワーカーがすべてのラムダタスクの作業が完了するのを待つ場合があります。

流れるようなインターフェイス

人間が読めるコードを簡潔に書くことができます。

accounts::erase(std::remove_if(accounts.begin(),accounts.end(),used_this_year));
std::for_each(accounts.begin(),accounts.end(),mark_dormant);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.