2

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.

Moritz
  • 35
  • 5
  • 1
    `int (&b)[3]` This is a reference to a `int[3]`. It's a tricky syntax. So you do have a reference to an array of length 3. – DeiDei May 19 '20 at 11:47
  • 1
    Your "reading" is unfortunately wrong, `int &(b)[3]` is parsed as an array of references, while `int (&b)[3]` is a reference to an array of size 3. (see https://stackoverflow.com/questions/5724171/passing-an-array-by-reference/5724184#5724184) – UnholySheep May 19 '20 at 11:48
  • Because `for(int i=0; i<3; i++) for(int j=0; j<3; j++) { std::cout << a[i][j] << std:endl;` would have been too readable and simple. So lets try to convolute that fast, readable code into oblivion, C++1x providing all the tools. Bonus points if the machine code also turns slower. – Lundin May 19 '20 at 11:55
  • I think `int (&b)[3]: a` is still way too readable. Do you have any ideas to make it even more unreadable? – Moritz May 19 '20 at 12:04
  • 1
    using I3 = int[3]; for(I3 &b: a) { // looks even worse here when I looks like 1. – QuentinUK May 19 '20 at 12:43

2 Answers2

1

int &(b[3]) is equivalent to int & b[3], i.e., an array of references to int whose length is three. This does not correspond to the type of the elements in the array int a[3][3].

The elements in the array int a[3][3] are of type int[3], i.e., an array of int whose length is three. By declaring instead b as int(&b)[3] you declare a reference to such a type.

JFMR
  • 23,265
  • 4
  • 52
  • 76
1

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....

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335