Advantages of std::for_each over for loop
Asked Answered
L

23

213

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?

Longitude answered 12/1, 2010 at 7:37 Comment(2)
std::for_each when used with boost.lambda or boost.bind can often improve readabilityDaemon
The question and accepted answer are from 2010. For a more uptodate answer (from 2018), see here:fluentcpp.com/2018/03/30/is-stdfor_each-obsoleteAbramabramo
P
207

The nice thing with C++11 (previously called C++0x), is that this tiresome debate will be settled.

I mean, no one in their right mind, who wants to iterate over a whole collection, will still use this

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

Or this

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

when the range-based for loop syntax is available:

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

This kind of syntax has been available in Java and C# for some time now, and actually there are way more foreach loops than classical for loops in every recent Java or C# code I saw.

Predicant answered 12/1, 2010 at 11:2 Comment(17)
Actually, a foreach loop with scoop has been available for a long time in boost, and I still want to iterate with for_each and a lambda function.Fondly
The assumption about wanting the entire container range isn't part of the question, so this is only a partial answer.Hypertonic
Note that looping over an element is probably not the only thing you want to do, so it can be a good idea to use for_each just so that you learn about find / partition / copy_replace_if and the others, which is what a lot for loops actually do.Armure
Range-for is nice, except when you actually need the iterator (then there's no way of getting to it).Codification
It is very likely that Element & e has to be const Element & eDyslalia
@Damon: I saw an outdirection_range adapter somewhere in boost::range once (can't find it now). That could be used to range--for-loop iterate over the iterators.Armure
@Macke: I'm not sure that would work with standard range-for since it's defined in a way so no iterator that you could pull out of your hat is available. Semantics have that you only ever get to see the dereferenced iterator.Codification
@Damon: Define a range/container adaptor whose begin()/end() returns an iterator whose value_type is the container's underlying iterator, so when dereferenced, you get the iterator itself, and that will be the inferred type when auto:ing the loop variable. It's certainly doable as I've used it occasionally at a previous job.Armure
I'd not use even Element & e as auto & e (or auto const &e) looks better. I'd use Element const e (without reference) when I want implicit conversion, say when the source is a collection of different types, and I want them to convert into Element.Cosmism
This doesn't answer the question. "Are there any advantages of std::for_each over for loop?"Goines
This is plain wrong. Using a range for, most of the time is a violation of the correct level of abstraction. fluentcpp.com/2018/03/30/is-stdfor_each-obsolete And I'm not even finished, about Element&: hard-type, auto and cv-qualification are not trivial to decide in that construct. c.f. the explanation why by Stephan Lavavej isocpp.org/blog/2014/01/n3853Dainedainty
what if you want to iterate over just a subset of your container? you can't use range-for directly using only std:: functionality (unless it is for (auto& e : boost::make_iterator_range(begin, middle) { ... }), whereas you can do it with std::for_each(begin, middle, ...).Advisedly
I tried the last example, with the range based for-loop, and it ran twice as fast as the other examples above. I'm compiling with VC++ x64 in release mode. Why is this the case? Is it because the iterator overhead is bypassed? Will this performance gain be seen compiling with gcc?Shipshape
@aj.toulan: what last example? repeated how many times? show reproducible code & context, or such anecdotes are meaningless.Toga
My bad @underscore_d. I'm sure I did 500, 1000 and 10000 iterations of a summation or something similar, it's been a while. I said in my comment it was the range-based example. Sorry I don't have the code sample, I also don't have easy access to a VC++ compiler anymore as I've switched to linux. In my comment, I wanted to see if anyone had noticed the same performance increase that I did. I guess that's not the case, but if you're interested you can experiment on your own. Seems you're more interested in attempting to ridicule me instead. So if you want another stab let's see it, lol.Shipshape
@Shipshape I'm not trying to ridicule you, just expect evidence for claims. Sorry if it came across otherwise.Toga
@Toga sorry I got so defensive. I see what you're saying. I wanted to share that I saw it run faster, not saying it is faster in all cases. I will definitely give instructions to replicate next time.Shipshape
A
62

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, parallel 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) + lambdas:

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

is IMO more readable than:

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

Also this:

for_each(bananas, [&](auto& b) { my_monkey.eat(b); );

Is more concise than:

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

But new range based for is probably the best:

 for (auto& b : bananas)
     my_monkey.eat(b);

But the for_each could be useful, especially if you have several functions to call in order but need to run each method for all objects before next... 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?

Armure answered 12/1, 2010 at 7:43 Comment(5)
+1, several functions or nested types: outer_class::inner_class::iterator or they are template arguments: typename std::vector<T>::iterator... the for construct itself can run into a many line construct in itselfThunderhead
(btw: the for_each in the second example is incorrect (should be for_each( bananas.begin(), bananas.end(),...Thunderhead
I've written wrappers that use ranges instead of two iterators. These will be available later (see range_ex) but everyone should have them anyway. (Added update on that.)Armure
Parallel processing support is no. 1 reason here. We can add implementation to use cuda/gpu for heterogeneous-parallel computing.Darell
I like the example with boost::bind, I guess we could replace it with std::bind. Do we gain any performance by for_each with bind?Quesenberry
D
27

for_each is more generic. You can use it to iterate over any type of container (by passing in the begin/end iterators). You can potentially swap out containers underneath a function which uses for_each without having to update the iteration code. You need to consider that there are other containers in the world than std::vector and plain old C arrays to see the advantages of for_each.

The major drawback of for_each is that it takes a functor, so the syntax is clunky. This is fixed in C++11 (formerly C++0x) with the introduction of lambdas:

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

This will not look weird to you in 3 years.

Damon answered 12/1, 2010 at 7:42 Comment(6)
@Marcus: that will be the ranged-for construct and the syntax will not read 'for_each' in itself: for ( int v : int_vector ) { (even if it can be simulated today with BOOST_FOREACH)Thunderhead
@David: I'm referring to the general addition of range-based functions (so you can use ranges with all these for_each, copy, remove_if, etc etc functions),Armure
Why is it not possible to write: std::for_each(container, [](int& i){ ... });. I mean why is one forced to write container twice?Bushweller
@Bushweller that is not "writting the container twice". The range [begin, end) is specified to std::for_each by giving the begin and the end iterators.Urfa
@freitass: Writing the container once as in my previous comment could default to using the begin end iterator without calling them explicitly. Most language that provide higher-order functions on collections (Ruby, Scala, ...) write something like container.each { ... } without mentioning begin and end iterators. I find it a bit redundant that I have to specify the end iterator all the time.Bushweller
@Giorgio: Sorry. I think the way I read your question in the first place made me perceive it that way.Urfa
C
18

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)));
Crofoot answered 12/1, 2010 at 8:20 Comment(0)
B
12

its very subjective, some will say that using for_each will make the code more readable, as it allows to treat different collections with the same conventions. for_each itslef is implemented as a loop

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

so its up to you to choose what is right for you.

Botanical answered 12/1, 2010 at 7:43 Comment(0)
P
11

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;
      }
   }
}
Parotitis answered 12/1, 2010 at 7:52 Comment(1)
You make a good point, but your motivation example isn't entirely fair. When you use std::for_each() in the old standard (that of the time of this post) you have to use a named functor, which encourages readability as you say and prohibits breaking out of the loop prematurely. But then the equivalent for loop has nothing but a function call, and that too prohibits breaking out prematurely. But other than that I think you made an excellent point in saying that std::for_each() enforces going through the entire range.Requite
M
11

You're mostly correct: most of the time, std::for_each is a net loss. I'd go so far as to compare for_each to goto. goto provides the most versatile flow-control possible -- you can use it to implement virtually any other control structure you can imagine. That very versatility, however, means that seeing a goto in isolation tells you virtually nothing about what's it's intended to do in this situation. As a result, almost nobody in their right mind uses goto except as a last resort.

Among the standard algorithms, for_each is much the same way -- it can be used to implement virtually anything, which means that seeing for_each tells you virtually nothing about what it's being used for in this situation. Unfortunately, people's attitude toward for_each is about where their attitude toward goto was in (say) 1970 or so -- a few people had caught onto the fact that it should be used only as a last resort, but many still consider it the primary algorithm, and rarely if ever use any other. The vast majority of the time, even a quick glance would reveal that one of the alternatives was drastically superior.

Just for example, I'm pretty sure I've lost track of how many times I've seen people writing code to print out the contents of a collection using for_each. Based on posts I've seen, this may well be the single most common use of for_each. They end up with something like:

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

And their post is asking about what combination of bind1st, mem_fun, etc. they need to make something like:

std::vector<XXX> coll;

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

work, and print out the elements of coll. If it really did work exactly as I've written it there, it would be mediocre, but it doesn't -- and by the time you've gotten it to work, it's difficult to find those few bits of code related to what's going on among the pieces that hold it together.

Fortunately, there is a much better way. Add a normal stream inserter overload for XXX:

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

and use std::copy:

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

That does work -- and takes virtually no work at all to figure out that it prints the contents of coll to std::cout.

Massey answered 12/1, 2010 at 17:4 Comment(7)
+1, There's one mistake though. In first example it should be boost::mem_fn(&XXX::print) rather than XXX::printLongitude
That's why I said that example won't work, and they're posting asking for help to get it work (oh, and you also need to bind std::cout as its argument for it to work).Massey
Although it's generally a good answer, the question is not about for_each's value or its value compared to other std algorithms, but about its value compared to a for loop. You may think of it in cases where no other std algorithm applies. Would you then use a for_each or a for loop? Think about it and whatever you come up with, that should've been your answer.Ufa
@ChristianRau: There's always a fine line between answering the question exactly as asked, and trying to provide useful information. The direct answer to exactly the questions he asked would be "Probably not. Who knows?", but would be too useless to be worth the bother. At the same time going too far afield (e.g., recommending Haskell instead of any of the above) isn't likely to be of much use either.Massey
@ChristianRau: I should add that IMO, your downvote is thoroughly unwarranted. If we consistently followed the narrow view you seem to be taking of what constitutes a helpful answer, it looks to me like your reputation would be 0 (and only escape being negative because they site doesn't allow it).Massey
@JerryCoffin Since it didn't answer the question in any way, I stand to my down-vote. Nothing against providing additional information, but at least some words on the actual question would have sufficed for separating it from a (though good, but also quite long) comment.Ufa
@ChristianRau: How do you figure that "...most of the time, std::for_each is a net loss" doesn't address the question of whether std::for_each provides an advantage?Massey
F
9

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

Fondly answered 12/1, 2010 at 21:12 Comment(1)
Maybe my opinion sucks, but I prefer to read the structured code, cpp11's for(:) makes second bit much easier to read.Winsome
A
8

Easy: for_each is useful when you already have a function to handle every array item, so you don't have to write a lambda. Certainly, this

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

is better than

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

Also, ranged for loop only iterates over whole containers from start to end, whilst for_each is more flexible.

Aspergillus answered 9/8, 2016 at 15:24 Comment(2)
Why is for_each better in this case? I think ranged for is better because I like being able to step through code with a debugger rather than dropping a breakpoint in some function used in many places.Winsome
Stepping through a loop with a debugger is only an option when the collection is small. Normally you would set a conditional breakpoint inside handler function.Aspergillus
M
4

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)

Malchus answered 12/1, 2010 at 8:0 Comment(0)
T
3

Aside from readability and performance, one aspect commonly overlooked is consistency. There are many ways to implement a for (or while) loop over iterators, from:

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

to:

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

with many examples in between at varying levels of efficiency and bug potential.

Using for_each, however, enforces consistency by abstracting away the loop:

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

The only thing you have to worry about now is: do you implement the loop body as function, a functor, or a lambda using Boost or C++0x features? Personally, I'd rather worry about that than how to implement or read a random for/while loop.

Tumultuous answered 12/1, 2010 at 8:52 Comment(0)
D
3

I used to dislike std::for_each and thought that without lambda, it was done utterly wrong. However I did change my mind some time ago, and now I actually love it. And I think it even improves readability, and makes it easier to test your code in a TDD way.

The std::for_each algorithm can be read as do something with all elements in range, which can improve readability. Say the action that you want to perform is 20 lines long, and the function where the action is performed is also about 20 lines long. That would make a function 40 lines long with a conventional for loop, and only about 20 with std::for_each, thus likely easier to comprehend.

Functors for std::for_each are more likely to be more generic, and thus reusable, e.g:

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

And in the code you'd only have a one-liner like std::for_each(v.begin(), v.end(), DeleteElement()) which is slightly better IMO than an explicit loop.

All of those functors are normally easier to get under unit tests than an explicit for loop in the middle of a long function, and that alone is already a big win for me.

std::for_each is also generally more reliable, as you're less likely to make a mistake with range.

And lastly, compiler might produce slightly better code for std::for_each than for certain types of hand-crafted for loop, as it (for_each) always looks the same for compiler, and compiler writers can put all of their knowledge, to make it as good as they can.

Same applies to other std algorithms like find_if, transform etc.

Duel answered 12/1, 2010 at 10:55 Comment(0)
K
3

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

Kirovabad answered 18/8, 2013 at 8:24 Comment(0)
P
3

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); }
Porky answered 18/8, 2013 at 17:13 Comment(0)
M
2

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.

Multiform answered 12/1, 2010 at 7:47 Comment(2)
not if you pass it an iterator which advances by 3 with each ++. Unusual maybe, but so is a for-loop doing the same.Shillelagh
In that case maybe it'll better to use transform to not to confuse someone.Multiform
D
2

for_each allow us to implement Fork-Join pattern . Other than that it supports fluent-interface.

fork-join pattern

We can add implementation gpu::for_each to use cuda/gpu for heterogeneous-parallel computing by calling the lambda task in multiple workers.

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

And gpu::for_each may wait for the workers work on all the lambda-tasks to finish before executing the next statements.

fluent-interface

It allow us to write human-readable code in concise manner.

accounts::erase(std::remove_if(accounts.begin(),accounts.end(),used_this_year));
std::for_each(accounts.begin(),accounts.end(),mark_dormant);
Darell answered 8/8, 2018 at 21:30 Comment(0)
B
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.

Bydgoszcz answered 12/1, 2010 at 9:5 Comment(0)
C
1

I find for_each to be bad for readability. The concept is a good one but c++ makes it very hard to write readable, at least for me. c++0x lamda expressions will help. I really like the idea of lamdas. However on first glance I think the syntax is very ugly and I'm not 100% sure I'll ever get used to it. Maybe in 5 years I'll have got used to it and not give it a second thought, but maybe not. Time will tell :)

I prefer to use

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

I find an explicit for loop clearer to read and explicity using named variables for the start and end iterators reduces the clutter in the for loop.

Of course cases vary, this is just what I usually find best.

Claque answered 12/1, 2010 at 11:21 Comment(0)
H
1

There are a lot of good reasons in other answers but all seem to forget that for_each allows you to use reverse or pretty much any custom iterator when for loop always starts with begin() iterator.

Example with reverse iterator:

std::list<int> l {1,2,3};
std::for_each(l.rbegin(), l.rend(), [](auto o){std::cout<<o;});

Example with some custom tree iterator:

SomeCustomTree<int> a{1,2,3,4,5,6,7};
auto node = a.find(4);
std::for_each(node.breadthFirstBegin(), node.breadthFirstEnd(), [](auto o){std::cout<<o;});
Horseflesh answered 12/9, 2020 at 7:15 Comment(0)
M
0

You can have the iterator be a call to a function that is performed on each iteration through the loop.

See here: http://www.cplusplus.com/reference/algorithm/for_each/

Motherofpearl answered 12/1, 2010 at 7:42 Comment(1)
Link-only posts do not make good answers, and anyway, where in that link does it show anything resembling a callable iterator? I'm pretty sure that concept just doesn't make sense. Maybe you were just summarising what for_each does, in which case, it doesn't answer the question about its advantages.Toga
B
0

For loop can break; I dont want to be a parrot for Herb Sutter so here is the link to his presentation: http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-835T Be sure to read the comments also :)

Bobettebobina answered 14/11, 2011 at 10:7 Comment(0)
F
0

std::for_each is great when you don't have a range.

For example, consider std::istream_iterator:

using Iter = std::istream_iterator<int>;

for (Iter i(str); i != Iter(); ++i) {
    f(*i);
}

It has no container, so you can't easily use a for (auto &&item: ...) loop, but you can do:

std::for_each(Iter(str), Iter(), [](int item)
    // ...
});
Fluttery answered 21/3, 2022 at 1:37 Comment(0)
K
0

As of C++2x, you can empower your std::for_each with ranges std::ranges::for_each and pipe all complex and nested loops into nice pipe-delemited and readable loops

Kenley answered 14/8, 2023 at 8:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.