Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Range-for-statement cannot build range expression with array function parameter

Tags:

c++

Why cannot build range expression passing an array as a function argument and using in a range-for-statement. Thanks for the help

void increment(int v[]){
    // No problem
    int w[10] = {9,8,7,6,5,4,3,2,1,9};
    for(int& x:w){
        std::cout<<"range-for-statement: "<<++x<<"\n";
    }

    // error: cannot build range expression with array function 
    // parameter 'v' since parameter with array type 'int []' is 
    // treated as pointer type 'int *'
    for(int x:v){
        std::cout<<"printing "<<x<<"\n";
    }

    // No problem
    for (int i = 0; i < 10; i++){
        int* p = &v[i];             
    }
}

int main()
{
    int v[10] = {9,8,7,6,5,4,3,2,1,9};
    increment(v);
}
like image 507
Pompeyo Avatar asked Jun 08 '14 10:06

Pompeyo


3 Answers

Despite appearances, v is a pointer not an array - as the error message says. Built-in arrays are weird things, which can't be copied or passed by value, and silently turn into pointers at awkward moments.

There is no way to know the size of the array it points to, so no way to generate a loop to iterate over it. Options include:

  • use a proper range-style container, like std::array or std::vector
  • pass the size of the array as an extra argument, and interate with an old-school loop
like image 67
Mike Seymour Avatar answered Oct 21 '22 21:10

Mike Seymour


It's because of the way you pass the array to the function. As written it decays to pointer. Try

template<int N>
void increment(int (&v)[N])
{
    for (int x : v) std::cout << "printing " << x << "\n";
}

int main()
{
    int v[10] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 9 };
    increment(v);
}

This runs because a reference to an array of N ints is passed in the function and (unlike pointers) range for loops can iterate on those.

like image 22
Nikos Athanasiou Avatar answered Oct 21 '22 19:10

Nikos Athanasiou


The function parameter int v[] is adjasted to int * Pointers do not keep information whether they point a single object or the first object of a sequence of objects.

The range-based for statement in fact uses the same expressions as standard functions std::begin and std::end They cannot be defined for pointers without knowing the size of the array. They can be defined for arrays, not pointers.

like image 20
Vlad from Moscow Avatar answered Oct 21 '22 19:10

Vlad from Moscow