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:
parameter ‘arr’ includes reference to array of unknown bound ‘T [][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?
source to share
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]) {}
source to share
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 boundaryT
", 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}};
source to share