Search code examples
c++arraysfor-loopauto

C++: Nested For-loops over 2 dimensional array with "auto"


To loop over a 3x3 array called "a" in C++ i used the following code.

int a[3][3] {};
for(auto &b: a) {
  for(auto &c: b) {
    std::cout << c << std::endl;
  }
}

If I had to replace the "auto", I would intuitively try

int a[3][3] {};
for(int &(b[3]): a) {
  for(int &c: b) {
    std::cout << c << std::endl;
  }
}

But this does not work. Instead I figured out that the following works.

int a[3][3] {};
for(int (&b)[3]: a) {
  for(int &c: b) {
    std::cout << c << std::endl;
  }
}

So the question is: Why does the latter example work?

I thought I needed a reference to an array of length 3, but instead I need an array of length 3 containing references.


Solution

  • If you have an array like this

    T a[N1][N2][N3];
    

    where T is some type specifier and N1, N2, and N3 the sizes of the array then a reference to this array will look like

    T ( &ra )[N1][N2][N3]  = a;
    

    If you need to declare a reference to the element of the array that (the element) has the type T[N2][N3] then you can write for example

    T ( &e )[N2][N3] = a[0];
    

    Returning to your example you declared an array

    int a[3][3] {};
    

    elements of this array have the type int[3]. So to declare a reference to elements of the array you have to write

    for ( int ( %row )[3] : a )
    

    As for this declaration

    int &(b[3])
    

    (where the parentheses are redundant) then it declares an array of three elements with the type int &. However according to the C++ Standard you may not declare an array of references.

    From the C++ Standard (8.3.4 Arrays)

    1 In a declaration T D where D has the form

    D1 [ constant-expressionopt] attribute-specifier-seqopt
    

    and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T”, then the type of the identifier of D is an array type; if the type of the identifier of D contains the auto type-specifier, the program is ill-formed. T is called the array element type; this type shall not be a reference type, the (possibly cvqualified) type void, a function type or an abstract class type....