[c++] Advantages of std::for_each over for loop


8 Answers

Here are some reasons:

  1. It seems to hinder readability just because you're not used to it and/or not using the right tools around it to make it really easy. (see boost::range and boost::bind/boost::lambda for helpers. Many of these will go into C++0x and make for_each and related functions more useful.)

  2. It allows you to write an algorithm on top of for_each that works with any iterator.

  3. It reduces the chance of stupid typing bugs.

  4. It also opens your mind to the rest of the STL-algorithms, like find_if, sort, replace, etc and these won't look so strange anymore. This can be a huge win.

Update 1:

Most importantly, it helps you go beyond for_each vs. for-loops like that's all there is, and look at the other STL-alogs, like find / sort / partition / copy_replace_if, parallell execution .. or whatever.

A lot of processing can be written very concisely using "the rest" of for_each's siblings, but if all you do is to write a for-loop with various internal logic, then you'll never learn how to use those, and you'll end up inventing the wheel over and over.

And (the soon-to-be available range-style for_each):

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

Or with C++x11 lambdas:

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

is IMO more readable than:

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

Also this (or with lambdas, see others):

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

Is more concise than:

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

Especially if you have several functions to call in order... but maybe that's just me. ;)

Update 2: I've written my own one-liner wrappers of stl-algos that work with ranges instead of pair of iterators. boost::range_ex, once released, will include that and maybe it will be there in C++0x too?

Question

Are there any advantages of std::for_each over for loop? To me, std::for_each only seems to hinder the readability of code. Why do then some coding standards recommend its use?




The advantage of writing functional for beeing more readable, might not show up when for(...) and for_each(...).

If you utilize all algorithms in functional.h, instead of using for-loops, the code gets a lot more readable;

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);

is much more readable than;

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);
}

And that is what I think is so nice, generalize the for-loops to one line functions =)




If you frequently use other algorithms from the STL, there are several advantages to for_each:

  1. It will often be simpler and less error prone than a for loop, partly because you'll be used to functions with this interface, and partly because it actually is a little more concise in many cases.
  2. Although a range-based for loop can be even simpler, it is less flexible (as noted by Adrian McCarthy, it iterates over a whole container).
  3. Unlike a traditional for loop, for_each forces you to write code that will work for any input iterator. Being restricted in this way can actually be a good thing because:

    1. You might actually need to adapt the code to work for a different container later.
    2. At the beginning, it might teach you something and/or change your habits for the better.
    3. Even if you would always write for loops which are perfectly equivalent, other people that modify the same code might not do this without being prompted to use for_each.
  4. Using for_each sometimes makes it more obvious that you can use a more specific STL function to do the same thing. (As in Jerry Coffin's example; it's not necessarily the case that for_each is the best option, but a for loop is not the only alternative.)




Like many of the algorithm functions, an initial reaction is to think it's more unreadable to use foreach than a loop. It's been a topic of many flame wars.

Once you get used to the idiom you may find it useful. One obvious advantage is that it forces the coder to separate the inner contents of the loop from the actual iteration functionality. (OK, I think it's an advantage. Other's say you're just chopping up the code with no real benifit).

One other advantage is that when I see foreach, I know that either every item will be processed or an exception will be thrown.

A for loop allows several options for terminating the loop. You can let the loop run its full course, or you can use the break keyword to explicitly jump out of the loop, or use the return keyword to exit the entire function mid-loop. In contrast, foreach does not allow these options, and this makes it more readable. You can just glance at the function name and you know the full nature of the iteration.

Here's an example of a confusing for loop:

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;
      }
   }
}



for is for loop that can iterate each element or every third etc. for_each is for iterating only each element. It is clear from its name. So it is more clear what you are intending to do in your code.




With C++11 and two simple templates, you can write

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

as a replacement for for_each or a loop. Why choose it boils down to brevity and safety, there's no chance of error in an expression that's not there.

For me, for_each was always better on the same grounds when the loop body is already a functor, and I'll take any advantage I can get.

You still use the three-expression for, but now when you see one you know there's something to understand there, it's not boilerplate. I hate boilerplate. I resent its existence. It's not real code, there's nothing to learn by reading it, it's just one more thing that needs checking. The mental effort can be measured by how easy it is to get rusty at checking it.

The templates are

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); }



Personally, any time I'd need to go out of my way to use std::for_each (write special-purpose functors / complicated boost::lambdas), I find BOOST_FOREACH and C++0x's range-based for clearer:

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

vs

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



Mostly you'll have to iterate over the whole collection. Therefore I suggest you write your own for_each() variant, taking only 2 parameters. This will allow you to rewrite Terry Mahaffey's example as:

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

I think this is indeed more readable than a for loop. However, this requires the C++0x compiler extensions.




The for_each loop is meant to hide the iterators (detail of how a loop is implemented) from the user code and define clear semantics on the operation: each element will be iterated exactly once.

The problem with readability in the current standard is that it requires a functor as the last argument instead of a block of code, so in many cases you must write specific functor type for it. That turns into less readable code as functor objects cannot be defined in-place (local classes defined within a function cannot be used as template arguments) and the implementation of the loop must be moved away from the actual loop.

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
}

Note that if you want to perform an specific operation on each object, you can use std::mem_fn, or boost::bind (std::bind in the next standard), or boost::lambda (lambdas in the next standard) to make it simpler:

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

Which is not less readable and more compact than the hand rolled version if you do have function/method to call in place. The implementation could provide other implementations of the for_each loop (think parallel processing).

The upcoming standard takes care of some of the shortcomings in different ways, it will allow for locally defined classes as arguments to templates:

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

Improving the locality of code: when you browse you see what it is doing right there. As a matter of fact, you don't even need to use the class syntax to define the functor, but use a lambda right there:

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

Even if for the case of for_each there will be an specific construct that will make it more natural:

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

I tend to mix the for_each construct with hand rolled loops. When only a call to an existing function or method is what I need (for_each( v.begin(), v.end(), boost::bind( &Type::update, _1 ) )) I go for the for_each construct that takes away from the code a lot of boiler plate iterator stuff. When I need something more complex and I cannot implement a functor just a couple of lines above the actual use, I roll my own loop (keeps the operation in place). In non-critical sections of code I might go with BOOST_FOREACH (a co-worker got me into it)




Related