Q:

C++ error from passing an integer array as a parameter

Followup to Range-for-statement cannot build range expression with array function parameter.
The original error is:

error: cannot build range expression with array function parameter 'arr' since parameter with array type 'int []' is treated as pointer type 'int *'

The failing code:
void print(int (&arr)[int]){
    for(int x: arr)
        cout<<" "<<x;
    cout<<endl;
}

The fixed code:
template<int N>
void print(int (&arr)[N]){
    for(int x: arr)
        cout<<" "<<x;
    cout<<endl;
}

My question is, why do we have to fix it like this? I do not understand what int (&arr)[int] means.

A:

Your question is a little confusing because your first example is not valid code.
However, I think there is still an explanation to provide here. Here's a "correct" version of your first function:
void print(int (&arr)[5]){
    for(int x: arr)
        cout<<" "<<x;
    cout<<endl;
}

void foo() {
    int x[5];
    int y[3];

    print(x);
    print(y); // Bam! error!
}

The print() function takes an array of 5 ints as a parameter. Note that this can only be done with statically sized arrays. The compiler must know the size of the array when compiling the function, and that function will only work for that particular array size.
Let's contrast that with your second, valid example.
A single array size, that's kind of annoying. What if I don't want to write a different function for various array sizes? We could always pass a pointer and a size, but that's kind of ugly (not to mention error prone).
Instead, we can give the compiler a function template. That is, not a function, but a recipe on how to create functions on-demand.
template<int N>
void print(int (&arr)[N]){
    for(int x: arr)
        cout<<" "<<x;
    cout<<endl;
}

The constant 5 has been replaced by the placeholder constant N (which will have to be an int, as specified in the template declaration. This way, the compiler will generate a separate print() function for each array size we call it with.

