Reputation: 2229
I only just recently discovered that Visual C++ 2008 (and perhaps earlier versions as well?) supports for each
syntax on stl lists et al to facilitate iteration.
For example:
list<Object> myList;
for each (Object o in myList)
{
o.foo();
}
I was very happy to discover it, but I'm concerned about portability for the dreaded day when someone decides I need to be able to compile my code in say, gcc or some other compiler. Is this syntax widely supported and can I use it without worrying about portability issues?
Upvotes: 24
Views: 21613
Reputation: 18203
Your code is indeed not portable.
The following works with the C++ 0x standard and Visual C++ 2010 (which doesn't support the new "ranged for" syntax as far as I can tell).
#define for_each(_ITER_, _COLL_) for (auto _ITER_ = _COLL_.begin(); \
_ITER_ != _COLL_.end(); _ITER_++)
Now you can write:
list<Object> myList;
for_each (o, myList)
{
o.foo();
}
Compare this to the BOOST_FOREACH macro code at http://www.boost.org/doc/libs/1_48_0/boost/foreach.hpp which is not only complex it also has a number of dependencies on other boost libraries.
Upvotes: 1
Reputation: 3274
For each is not standard C or C++ syntax. If you want to be able to compile this code in gcc or g++, you will need to create an iterator and use a standard for loop.
QuantumPete
[edit] This seems to be a new feature introduced into MS Visual C++, so this is definitely not portable. Ref: http://msdn.microsoft.com/en-us/library/xey702bw%28VS.80%29.aspx [/edit]
Upvotes: 25
Reputation: 97091
If you'd like to use foreach and in the same time you don't want to add additional dependency (such as Boost) - this macro will help you:
#define VAR(V,init) __typeof(init) V=(init)
#define FOREACH(I,C) for(VAR(I,(C).begin());I!=(C).end();I++)
std::vector<int> numbers;
FOREACH(I, numbers)
{
std::cout << *I << std::endl;
}
Upvotes: 6
Reputation: 82041
Visual C++ "for each" is not standard C++, meaning you won't be able to compile your code on other compilers such as g++. However, the STL proposes std::for_each, but its syntax is a lot less intuitive. Here is its prototype:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f);
It takes two iterators defining a valid range, and applies the unary function (or functor) f to each object in this range. You can rewrite your example using std::for_each like this:
void foo(Object o)
{
o.foo();
}
...
list<Object> myList;
std::for_each(myList.begin(), myList.end(), foo);
However, if you want to stay close to the classical syntax of the for each construct, and if you're ok about using Boost, you can use BOOST.FOREACH, which will let you write
list<Object> myList;
BOOST_FOREACH(Object o, myList)
{
o.foo();
}
Upvotes: 5
Reputation: 100648
I wouldn't use that. While it's a tempting feature, the syntax is incompatible with the upcoming C++0x standard, which uses:
list<Object> myList;
for (Object o : myList)
{
o.foo();
}
to do the same thing.
Upvotes: 35
Reputation: 5951
I also recommend BOOST_FOREACH. I usually create a macro along the lines of:
#define _foreach(x,y) BOOST_FOREACH(x,y)
This tends to increase readability. You have to be careful about collisions with other foreach implementations though. For instance, Qt provides a 'foreach' and there's the std::for_each.
I find that the std::for_each doesn't actually save much time since you end up making lots of one-off function objects to supply to the for_each call. It's usually just as fast to make standard for-loop using STL iterators.
Upvotes: 0
Reputation: 520
My vote goes for Luc,
Stick to the standard STL algorithms and you will be better off by far. STL algorithms can make your life very easy, efficient and safe. Take a look at the off the shelve algorithms like find_if, count, count_if, sort, transform, etc...
Point 5 onwards... http://www.sgi.com/tech/stl/table_of_contents.html
Boost is cool, but if you are going to use it just for the FOR_EACH macro it is too much cumbersome regarding the development/build environment setup.
use boost when standard c++ / stl cannot solve the problem in an 'easy' way.
Upvotes: -1
Reputation: 545528
There is a very good portable alternative: Boost.Foreach. Just dump this header into your project and you can write your loops as follows:
list<Object> myList;
BOOST_FOREACH(Object o, myList)
o.foo();
Upvotes: 21