views:

501

answers:

9

I am using a lot of STL code with std::for_each, bind, and so on, but I noticed that sometimes STL usage is not good idea.

For example if you have a std::vector and want to do one action on each item of the vector, your first idea is to use this:

std::for_each(vec.begin(), vec.end(), Foo())

and it is elegant and ok, for a while. But then comes the first set of bug reports and you have to modify code. Now you should add parameter to call Foo(), so now it becomes:

std::for_each(vec.begin(), vec.end(), std::bind2nd(Foo(), X))

but that is only temporary solution. Now the project is maturing and you understand business logic much better and you want to add new modifications to code. It is at this point that you realize that you should use old good:

for(std::vector::iterator it = vec.begin(); it != vec.end(); ++it)

Is this happening only to me? Do you recognise this kind of pattern in your code? Have you experience similar anti-patterns using STL?

+10  A: 

Using boost::bind with std::for_each solves this problem in a clean way. Or you can use BOOST_FOREACH.

Example of std::for_each:

std::for_each(v.begin(), v.end(), boost::bind(&C::f, _1, param));

Example of BOOST_FOREACH:

std::list<int> list_int( /*...*/ );
BOOST_FOREACH( int i, list_int )
{
    // do something with i
}
Brian R. Bondy
...until you get to 10 parameters, that is! :)
Kylotan
at which point you group them together within a struct :)
Brian R. Bondy
No, at which point you reconsider the architecture that requires a function to have 10 parameters ;)
MadKeithV
That's exactly what I do. std::for_each is so ugly. BOOST_FOREACH is so much better
Edison Gustavo Muenz
+3  A: 

Similar to your issue, I often notice that the "functor" pattern / idiom in C++ is actually quite unwieldy. That's why I'm looking forward to Lambda Functions in C++0X. Some of that is possible with boost::lambda now.

MadKeithV
OMG, the syntax... 0X has 8 more months till it ends plus 3+ years until major compiler vendors catch up. That will be a long time.
Anton Gogolev
@Anton: It's already in g++ and Visual Studio 10 (RC freely available now)
Simon Buchan
+10  A: 

It can go the opposite way too though. Suppose you start out with an operation that only takes a couple of lines. You don't want to bother creating a fuction that will only be called once, just to condesnse the loop, so you write something like:

for ()
{
    // do
    // some
    // stuff
}

Then as the operation you need to perform gets more complex, you realize that pulling it into a separate function makes sense so you end up with

for ()
    do_alot_more_stuff();

And then modifying it to be like your original method makes sense to condense it down further:

std::for_each(begin, end, do_alot_more_stuff);

In the end, how hard is it to really change a for_each to a for loop, or vice versa? Don't beat yourself up over tiny details!

Greg Rogers
+4  A: 

Use it like any other language tool. When it makes your life easier, use it. When it becomes cumbersome, do something else. It's not as if it's really hard to refactor a loop one way or another, when requirements change.

David Thornley
Exactly. What's wrong with changing code?
Adam Jaskiewicz
A: 

Also think of Parallelism, with a function you can define what will change and indicate if a range of elements can instead be done in Parallel rather 1 at a time from start to end.

Greg Domjan
+1  A: 

Maybe you used for_each instead of transform in the first place...

Edouard A.
+1  A: 

I never use std::for_each (or very seldom).

I'd suggest using Boost.Foreach and classic "for" constructions for now. And when C++0x is out, you could consider using the new "for" construct, made more readable for iterating through containers.

Benoît
Can hardly wait for C++ to get a real "for" loop (rather than the glorififed while loop it has now).
T.E.D.
A: 

Or you could wait for C++0x and use for(elem& e, container){e.something();}
Quite the same as BOOST_FOREACH(), but part of the standard (in some years...).

tstenner
+1  A: 

I've had the same problem with a lot of the stuff in Algorithm. It has a nasty tendency to end up being more code that just using an old-fashioned for loop.

I can't really justify going off and creating some special functor class (which is a moderately advanced topic in C++ that many of my maintainers won't fully understand) with a proper constructor and destructor, and perhaps some accessors, simply to avoid a one-line for loop.

T.E.D.