Category / C++

Interesting (To me) July 6, 2014 at 2:10 pm

Looking through code recently written I noticed that I was using std::for_each where the new syntax of range based for would have sufficed.

Given how it was used, I don’t understand why I didn’t use the new syntax…

std::vector < int > vec;

for( int c : vec )
{
    //...
}

vs…

std::vector < int > vec;

std::for_each( vec.begin(), vec.end(), [&]( int c )
{
    //...
} );

The new range based for is much easier to understand in this case. As far as code generation, both are fairly close to identical in an optimized build. If a lambda expression is required either expression can be used (‘just’ call the lambda in the loop). The only real place the std::for_each ~should~ be used is likely when the range is a subrange. I have many times wondered why for_each didn’t have an overload like so:

std::for_each( vec, [&]( int c ) 
{
    //...    
} );

or…
using string_map = std::map < std::string, int >;

string_map items;
//..

auto es = items.equal_range( "E" );

std::for_each( es, [&]( string_map::value_type& v )
{
    //...
} );

Without aliases (or auto) try typing in the second expression. The pair<...> returned by equal range as a raw type is exceptionally painful to type, let alone read.

In general I prefer simpler looking code over more complex. (Ever looked through the std:: headers? Yipes!) Often while reviewing code a few days after writing it, I will notice that I could have done things a little better. When I am in control of the project I am not afraid to refactor.

Ernie