I think there are some other differences not yet covered by the answers so far.
-
a
for_eachcan accept any appropriate callable object, allowing one to ‘recycle’ the loop body for different for loops. For example (pseudo code)for( range_1 ) { lengthy_loop_body } // many lines of code for( range_2 ) { lengthy_loop_body } // the same many lines of code againbecomes
auto loop_body = some_lambda; // many lines of code here only std::for_each( range_1 , loop_body ); // a single line of code std::for_each( range_2 , loop_body ); // another single line of codethus avoiding duplication and simplifying code maintenance. (Of course, in a funny mix of styles one could also use a similar approach with the
forloop.) -
another difference regards breaking out of the loop (with
breakorreturnin theforloop). As far as I know, in anfor_eachloop this can only be done by throwing an exception. For examplefor( range ) { some code; if(condition_1) return x; // or break more code; if(condition_2) continue; yet more code; }becomes
try { std::for_each( range , [] (const_reference x) { some code; if(condition_1) throw x; more code; if(condition_2) return; yet more code; } ); } catch(const_reference r) { return r; }with the same effects regarding calling of destructors for objects with scope of the loop body and the function body (around the loop).
-
the main benefit of
for_eachis, IMHO, that one can overload it for certain container types, when plain iteration is not as efficient. For example, consider a container that holds a linked list of data blocks, each block containing a contiguous array of elements, similar to (omitting irrelevant code)namespace my { template<typename data_type, unsigned block_size> struct Container { struct block { const block*NEXT; data_type DATA[block_size]; block() : NEXT(0) {} } *HEAD; }; }then an appropriate forward iterator for this type would require to check for the end of block at each increment and the comparison operator needs to compare both the block pointer and the index within each block (omitting irrelevant code):
namespace my { template<typename data_type, unsigned block_size> struct Container { struct iterator { const block*B; unsigned I; iterator() = default; iterator&operator=(iterator const&) = default; iterator(const block*b, unsigned i) : B(b), I(i) {} iterator& operator++() { if(++I==block_size) { B=B->NEXT; I=0; } // one comparison and branch return*this; } bool operator==(const iterator&i) const { return B==i.B && I==i.I; } // one or two comparisons bool operator!=(const iterator&i) const { return B!=i.B || I!=i.I; } // one or two comparisons const data_type& operator*() const { return B->DATA[I]; } }; iterator begin() const { return iterator(HEAD,0); } iterator end() const { return iterator(0,0); } }; }this type of iterator works correctly with
forandfor_each, for examplemy::Container<int,5> C; for(auto i=C.begin(); i!=C.end(); // one or two comparisons here ++i) // one comparison here and a branch f(*i);but requires two to three comparisons per iteration as well as a branch. A more efficient way is to overload the
for_each()function to loop on the block pointer and index separately:namespace my { template<typename data_type, int block_size, typename FuncOfDataType> FuncOfDataType&& for_each(typename my::Container<data_type,block_size>::iterator i, typename my::Container<data_type,block_size>::iterator const&e, FuncOfDataType f) { for(; i.B != e.B; i.B++,i.I=0) for(; i.I != block_size; i.I++) f(*i); for(; i.I != e.I; i.I++) f(*i); return std::move(f); } } using my::for_each; // ensures that the appropriate using std::for_each; // version of for_each() is usedwhich requires only one comparison for most iterations and has no branches (note that branches can have a nasty impact on performance). Note that we don’t need to define this in namespace
std(which might be illegal), but can ensure that the correct version is used by appropriateusingdirectives. This is equivalent tousing std::swap;when specialisingswap()for certain user-defined types.