Enhanced FOR loops in C++

JavaC++For Loop

Java Problem Overview


I am switching from Java to C++ and I was wondering whether C++ contains the enhanced for loops that I used in java, in example:

int[] numbers = {1,2,3,4,5,6,7,8,9,10};
for (int item : numbers) {
  System.out.println("Count is: " + item);
}

Is this same "shortcut" possible in C++?

Java Solutions


Solution 1 - Java

C++11 does. They are called range-based fors. Remember that you should qualify the type as a reference or a reference to const.

The workaround for C++03 is BOOST_FOR_EACH or boost::bind in combination with std::for_each. More fancy things are possible with Boost.Lambda. Should you be in the mood to frustrate either yourself or your co-workers I recommend the deprecated binders std::bind1st and std::bind2nd.

Here is some example code:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <boost/lambda/lambda.hpp>
#include <functional>    

int main()
{
  int i = 0;
  std::vector<int> v;
  std::generate_n(std::back_inserter(v), 10, [&]() {return i++;});

  // range-based for
  // keep it simple
  for(auto a : v)
    std::cout << a << " ";
  std::cout << std::endl;

  // lambda
  // i don't like loops
  std::for_each(v.begin(), v.end(), [](int x) { 
      std::cout << x << " ";
    });
  std::cout << std::endl;

  // hardcore
  // i know my lib
  std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;


  // boost lambda
  // this is what google came up with
  // using for the placeholder, otherwise this looks weird
  using namespace boost::lambda;
  std::for_each(v.begin(), v.end(), std::cout << _1 << " ");
  std::cout << std::endl;
  
  // fold
  // i want to be a haskell programmer
  std::accumulate(v.begin(), v.end(), std::ref(std::cout), 
                  [](std::ostream& o, int i) -> std::ostream& { return o << i << " "; });

  return 0;
}

Solution 2 - Java

In C++11, if your compiler supports it, yes it is. It's called range-based for.

std::vector<int> v;

// fill vector

for (const int& i : v) { std::cout << i << "\n"; }

It works for C style arrays and any type that has functions begin() and end() that return iterators. Example:

class test {
    int* array;
    size_t size;
public:
    test(size_t n) : array(new int[n]), size(n)
    {
        for (int i = 0; i < n; i++) { array[i] = i; }
    }
    ~test() { delete [] array; }
    int* begin() { return array; }
    int* end() { return array + size; }
};

int main()
{
    test T(10);
    for (auto& i : T) {
        std::cout << i;   // prints 0123456789
    }
}

Solution 3 - Java

There is no such a possibility in C++03. However new standard (C++11) does have it. See example (taken from Wikipedia):

int my_array[5] = {1, 2, 3, 4, 5};
for (int &x : my_array) {
    x *= 2;
}

Consider also using std::vector<int> instead of an ordinary array. This is C++ analogy for C data types, which makes life easier.

Solution 4 - Java

Yes and no.

1. Local array: No, but you can easily find the size

If you have a local array (int numbers[4] = {1, 2, 3, 4];) then you can do size = sizeof(numbers) / sizeof(int).

2. Pointer to array: Not at all, you have to pass the size around separately

If you have a pointer to an array (int* numbers = new int[4];) then you can't figure out the size unless you keep track of it yourself. (or if it's null terminated in the case of a c string, but then you have to iterate through it which is linear running time...)

Note that I don't believe pointer to array is the proper terminology, really you just have a pointer to the first element of the array but space for multiple values has been allocated. Not sure what this is called. Maybe just a pointer?

3. STL containers: Yes, and you can do some for loop magic using iterators, or just use indices by getting the size

If you have a vector (std::vector<int> v(3, 0);) then you can iterate through it the following ways:

C++11:

auto it = v.begin();
for (auto it = v.begin(); it != v.end(); it++)
{
    UseElement(*it);
}

Or apparently (also C++11, thanks jrok):

for (const int& i : v) { UseElement(i); }

C++ (pre-11):

std::vector<int>::iterator it;
for (it = v.begin(); it != v.end(); it++)
{
    UseElement(*it);
}

Or using indices:

for (int i = 0; i < v.size(); i++)
{
    UseElement(v[i]);
}

Furthermore, you can use function pointers or functors with STL containers using std algorithm's for_each (#include <algorithm>) like so:

void foo(int i)
{
    std::cout << i;
}

{
    std::for_each(myvector.begin(), myvector.end(), foo);
}

Solution 5 - Java

In the old standard, C++03 (which is from 2003), the language has no built-in support for that kind of for-loop. There are some artifices you can use with Boost, but imo it's not worth including a whole new library for this small convenience feature.

In the new standard, C++11 (which was released just last summer), this is possible; the syntax looks like this:

MyType array[] = { ... }
for (MyType& x : array) {
    ...
}

Note that I'm using MyType& x, not MyType x. In Java everything is a reference. In C++ references have to be explicit, and you declare them using &. If you don't use references, the for-loop will copy each element of the array into x (which might be expensive to do).

However, C++11 is not fully supported by most compilers yet. I think Microsoft's Visual C++ supports this feature, but I'm not sure.

Solution 6 - Java

Others already mentioned that this loop style was added in C++11. However C++11 is even better:

for (auto const& item: numbers)
{
  std::cout << "Count is: " << item << '\n';
}

That way, if you later change the element type of numbers from int to long, or even to some bigint class you wrote yourself, you don't need to change that for loop at all.

Solution 7 - Java

I find this simple macro very useful. The vast majority of my for loops involve iterating over an STL container:

#define For(it, container) for( typeof((container).begin()) it = (container).begin(); it != (container).end(); ++it)

An example:

vector<int> vector_of_ints;
... // initialize it somehow
For(integer, vector_of_ints) {
    cout << *integer << endl;
}

There are two things to be aware of with this: First, it's an iterator and hence you must dereference it. And second, the second parameter to the For will be evaluated many times. I have played with other approaches, but I keep returning to the simplicity of this.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaniel GratzerView Question on Stackoverflow
Solution 1 - JavapmrView Answer on Stackoverflow
Solution 2 - JavajrokView Answer on Stackoverflow
Solution 3 - JavaRoman ByshkoView Answer on Stackoverflow
Solution 4 - JavaAndrew RasmussenView Answer on Stackoverflow
Solution 5 - JavaPaul MantaView Answer on Stackoverflow
Solution 6 - JavaceltschkView Answer on Stackoverflow
Solution 7 - JavaAaron McDaidView Answer on Stackoverflow