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?


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]) {}




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 {
    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;

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





All Articles