views:

3713

answers:

8

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?

+9  A: 

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(VS.80).aspx [/edit]

QuantumPete
+1  A: 

The Boost Library has a portable ForEach imlementation.

dummy
+16  A: 

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();
Konrad Rudolph
+5  A: 

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();
}
Luc Touraille
Note: for each (a in b) seems to be CLR only even in VS 2005/2008 - you cannot use it in native code, only when targeting .NET, making for each even "less portable".Otherwise I think your answer is excellent.
Suma
A: 

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.

argatxa
A: 

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.

In Boost.Foreach documentation, they explicitly advise against the way you write your define. Write "#define _foreach BOOST_FOREACH" instead.
Luc Touraille
I like to keep it as BOOST_FOREACH simply because it reminds that it's a macro expansion and to be careful about what I put inside it.
Ferruccio
+6  A: 

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.

Ferruccio
+4  A: 

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;
}
Mike Hordecki