Why does the compiler not calculate the size of the array in case of passing a 2D array by reference

Just wondering - I wrote the following function

template <class T, size_t N>
T* asFlatArray (T arr[][N])
{
    // some code
}

      

and call it like

asFlatArray(myArray); // where myArray is int myArray[some_size][sime_size];

      

compilation works without errors. But if I change 'arr' to a link like

template <class T, size_t N>
T* asFlatArray (T (&arr)[][N])
{
    // some code
}

      

I will have errors:

parameterarrincludes reference to array of unknown boundT [][N]
      

I know how to fix this.

template <class T, size_t Rows, size_t Columns>
T* asFlatArray (T (&arr)[Rows][Columns])

      

but I don't understand why this is happening?

+3


source to share


2 answers


The main problem is that the first function template is equivalent to

template <class T, size_t N>
T* asFlatArray (T (*arr)[N]) {}

      

therefore there is no dimension to calculate. It will match a pointer to an array, or anything that decays to a pointer to an array. So a 2D array can match as well.



As for the second example, a reference or pointer to a type T[][N]

cannot be a function parameter, which results in a compiler error. Of course, you can add an additional template parameter for the missing dimension:

template <class T, size_t N, size_t M>
T* asFlatArray(T (&arr)[N][M]) {}

      

+5


source


The C ++ 11 and C ++ 14 standards in part [dcl.fct]/8 (8.3.5)

explicitly state:

If the parameter type includes the form type "pointer to array of unknown boundary T

" or "reference to array of unknown boundary T

", the program is poorly formed.

There is actually an active core language issue suggesting to remove this from the standard, so we might not see it in C ++ 17.



BTW, if the size of the array is indeed unknown, clang (but not gcc) compiles the code:

#include <iostream>

class A {
public:
    static int arr[][3];
};

// this compiles on clang but not gcc
void func(int (&arr_ref)[][3]) {
    std::cout << arr_ref[1][2] << std::endl;
}

int main() {
    int (&arr_ref)[][3] = A::arr;

    std::cout << A::arr[1][2] << std::endl;

    arr_ref[1][2] = 100;
    std::cout << A::arr[1][2] << std::endl;

    arr_ref[1][2] = 200;
    func(arr_ref); 
}

int A::arr[][3] = {{1, 2, 3}, {4, 5, 6}};

      

Demo

+1


source







All Articles