12

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?

3 Answers 3

23

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

Sign up to request clarification or add additional context in comments.

Comments

5

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);
}

Comments

2

Using C++20's std::span, you can have a reference to an array or runtime size.

Here's your code with std::span instead:

#include <iostream>
#include <span>

void foo(std::span<int>);

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

void foo(std::span<int> bar) {
  for (int i : bar) { // now works
    std::cout << i << std::endl;
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.