The C++ “for each” syntax


For Each?  I won’t go into a huge justification – suffice to say, there are some instances where it is nice to be able to iterate over a set, and perform operations on each member of that set.  A good primer might be the MSDN node on C# foreach.

A basic sample.  If you’re familiar with C++ for statements or the C# foreach statement, the C++ for each statement should be fairly familiar.  I’ll steal from a C# sample, and convert to C++:

using namespace System;

int main(){
  array<int>^ arr = gcnew array<int>{0,1,2,5,7,8,11};
  int even=0, odd=0;

  for each (int i in arr) {
    if (i%2 == 0) 
      even++;      
    else
      odd++;         
  }

  Console::WriteLine(“Found {0} Odd Numbers, and {1} Even Numbers.”,
    odd, even);
}

Pretty simple.  There are some definite advantages to for each.  Most importantly, it beats struggling with iterators and IEnumerables almost any day of the week.  There are also some interesting things you can do with for each.  For example, you can do fun things like for each(Char c in “abcdefg”).  Go crazy with Generic Collections.  And, here’s a code sample that I know will make some of you out there salivate:

#include <vector>
#include <iostream>
using namespace std;

int main() {
  int total = 0;

  vector<int> v(6);
  v[0] = 10; v[1] = 20; v[2] = 30;
  v[3] = 40; v[4] = 50; v[5] = 60;

  for each(int i in v) {
    total += i;
  }
 
  cout << total << endl;
}

Here’s the kicker: you can compile the above natively.  Why throw in the CLR if you don’t want to?  Of course, it compiles just fine with the CLR, but for each works on any STL-compliant container in native C++.  Now that’s a compiler improvement I can get behind.  Next time, I’ll take a first look at DF.  I think it’s going to take me a few posts to get it sorted out.

Comments (15)

  1. Anonymous says:

    I have a question, how does the c++/cli implement the c# "yield return" keyword’s function ?

  2. Anonymous says:

    The following is standard compliant C++ STL code for the same:

    for(int id = 0; i < v.size(); i++) {

    total += v[i];

    }

    I dont actually think that is any harder. Where’s the struggling with iterators? At least it is cross-platform.

  3. Anonymous says:

    >The following is standard compliant C++ STL code for the same:

    Yes, but only for vectors. You cannot iterate that way over set for example. Thus, the example does not do justice to this feature, and if you wanted generic portable code without "for each" you’d have to write:

    typedef container<type1, type2…> shorter;

    // replace container with concrete type, same goes to type parameters

    shorter sh;

    // fill in data here

    for(shorter::iterator it = sh.begin(); it != sh.end(); ++it)

    {

    total *= *it;

    // or something more complicated

    }

    Notice also that I used ++it and not it++. There is a subtle difference between these two, former being less expensive in general case (does not have to make a copy of iterator which might be expensive). This detail is hidden away in for each.

    So, all in all, it’s nice thing to have.

  4. Anonymous says:

    And don’t forget the STL for_each algorithm (to my mind one of the most overlooked bits of STL, probably due to the fact that parameter binders can be a bit of a pain…)

  5. Anonymous says:

    My use of a vector for the STL example was a bit short-sighted. I cover, a bit, by stating that for each can iterate over any STL container, but it really wasn’t the best example. Cheers to Drazen for cleaning that up for me, and for calling me on it.

    In the future, I pledge to do less of this "my dog ate my sample" nonsense. 🙂 Hey, everybody has off days, right? (No comments requesting links to my "on" days. My, uh, dog ate them.)

  6. Anonymous says:

    Paul Bartlett said:

    >> parameter binders can be a bit of a pain…

    They can, until you discover boost::bind (www.boost.org). I’d use boost::lambda as well/instead, but I’m still using VC6 🙁

  7. Anonymous says:

    Paul Bartlett said:

    >> parameter binders can be a bit of a pain…

    They can, until you discover boost::bind (www.boost.org). I’d use boost::lambda as well/instead, but I’m still using VC6 🙁

    BTW – Andy – it may be better not to use an ‘int’ array when demonstrating ‘for each’ – I have seen people assume that means that the iterating variable is actually an index into the array (which it clearly isn’t). If you used an array of strings or floats, the distinction would be clearer. It’s not just you, though, everyone demonstrating ‘for each’ (C# as well) seems to use a container of ints 🙂

  8. Anonymous says:

    Stuart, you make a good point about not using an ‘int’ collection for ‘for each’ examples. I could see how someone might get their thinking fouled up.

    I’m sorry to hear that you’re still on VC6 – especially if you’re a fan of boost. With Visual Studio 7.1 (".NET 2003"), we increased our template support fantastically, including partial specialization and partial ordering.

    See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/boostvc.asp for more details.

    Along with the increase in template support came a lot of extra testing. We made building boost one of our requirements for making sure our template support was good, and I heard there was even a little meta-programming contest. My personal favorite was the implementation of hanoi that displayed its result at compile time. 🙂

  9. Anonymous says:

    IMHO, the "for each" keyword is an abomination. It makes certain classes and interfaces "special" in that the compiler knows about them, which is completely unnecessary. Fundamentally this is a library function implemented as a keyword, and it alters the C++ syntax for no gain

    std::for_each does a pretty good job, especially when complemented by boost::lambda.

    I have also seen code that allows:

    std::vector<float> v;

    float total=0;

    for(each<float> f;f.in(v);)

    {

    total+=f;

    }

    which isn’t far off the code using the keyword, and is a purely library solution. As such, it is easily extensible to support traversing other types of container than just IEnumerables and containers yielding STL-style iterators.

  10. Anonymous says:

    If for each is such a good idea, then let’s get it in the standard. Otherwise, you’re just causing headaches for people who write cross platform code.

  11. Anonymous says:

    Is there a neat way of handling dictionaries?

    I have a Dictionary<Guid, Object^> and want to iterate over the values.

    Currently I have to use the syntax:

    for each(KeyValuePair<Guid, Object^> v in dict)

    {

    v.Value …

    }

    I can’t find an invocation that would allow

    for each (Object^ v in dict->Values)

    (This is using the Whidbey beta 1 compiler refresh).

  12. Anonymous says:

    http://www.sgi.com/tech/stl/accumulate.html

    #include <iostream>

    #include <vector>

    #include <numeric>

    using namespace std;

    int main() {

    vector<float> v;

    v.push_back(1.0);

    v.push_back(2.0);

    cout << "The sum of all elements in V is " << accumulate(v.begin(), v.end(), 0.0) << endl;

    return 0;

    }

  13. Anonymous says:

    To clarify – it’s only at work that I’m still on VC6!!! At home, I’ve been using VC7.1 since it came out – and I’ve been using VC8 since I was able to download that. At work, it’s a case of ‘big company IT policy’and ‘standard Windows 2000 builds’,which means that getting VS2003 (well, the .NET framework really) is not on the cards.

  14. Anonymous says:

    I’ve noticed that the C++/CLI spec for "for each" doesn’t match what the compiler does. The spec indicates that you have to introduce a new variable:

    foreach-statement:

    for each ( type ??-declaratoropt identifier in expression ) statement

    In reality, the identifier can refer to a variable defined in some enclosing scope. This is less commonly used, but is useful.

    The current compiler implementation has some problems. If the variable is a field of this, then the compiler will die. For example:

    class MyClass

    {

    public:

    int i;

    void Foo()

    {

    array<int>^ x = {1, 2, 3};

    for each (i in x)

    {

    if (i == 2) break;

    }

    }

    };