Range based for-loop on array passed to non-main function

When I try to compile the following code in gcc 4.8.2, I get the following error:

test.cc: In function ‘void foo(int*)’:
test.cc:15:16: error: no matching function for call to ‘begin(int*&)’
   for (int i : bar) {
                ^

Along with a bunch of others from deeper in the template library.

#include <iostream>
using namespace std;

void foo(int*);

int main() {
  int bar[3] = {1,2,3};
  for (int i : bar) {
    cout << i << endl;
  }
  foo(bar);
}

void foo(int* bar) {
  for (int i : bar) {
    cout << i << endl;
  }
}

If I redefine foo to use an indexed for loop, then the code compiles and behaves as expected. Also, if I move the range-based output loop into main, I get the expected behaviour as well.

How do I pass the array bar to foo in such a way that it is capable of executing a range-based for-loop on it?


Solution 1:

With the array decaying into a pointer you're losing one important piece of information: its size.

With an array reference your range based loop works:

void foo(int (&bar)[3]);

int main() {
  int bar[3] = {1,2,3};
  for (int i : bar) {
    cout << i << endl;
  }
  foo(bar);
}

void foo(int (&bar)[3]) {
  for (int i : bar) {
    cout << i << endl;
  }
}

or, in a generic fashion (i.e. without specifying the array size in the function signature),

template <std::size_t array_size>
void foo(int (&bar)[array_size]) {
  for (int i : bar) {
    cout << i << endl;
  }
}

Try it out

Solution 2:

For a fixed size array you can

  • Pass a raw array by reference.

  • Pass a std::array by reference.

  • Pass a std::vector by reference.

The natural choice (for a fixed size array) is std::array, i.e.

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

void foo(array<int, 3> const& bar) {
  for (int i : bar) {
    cout << i << endl;
  }
}

int main() {
  array<int,3> const bar = {1,2,3};
  for (int i : bar) {
    cout << i << endl;
  }
  foo(bar);
}