Using a pointer reference as a sequence in a C ++ 11 range for a loop

The only difference between the following two code snippets is the use of the link. I understand why the first fragment does not compile, and I am looking for help in understanding why the second is compiled.

The first fragment:

int a[2][3] = {0,1,2,3,4,5}; for (auto row : a) for (auto column : row) cout << column << endl; 

The above code does not compile because the type 'row' is a pointer to an int, which is not a sequence.

Second snippet:

 int a[2][3] = {0,1,2,3,4,5}; for (auto &row : a) for (auto column : row) cout << column << endl; 

This code compiles. If I understand correctly how auto works, 'row' is a reference to a pointer to an int. But why can this link be considered as a sequence more than a regular pointer?

+5
source share
3 answers

Type deduction is performed by subtracting the template argument.

 template <typename U> void foo(U&); // Equivalent to auto& foo(row); 

This will always output U as the exact type of row (if it is an lvalue as in this case), which gives us the type of array we wanted. For non-essential parameters only, attenuation from the array to the pointer is performed.

+5
source

Each element of the external iteration is an array. In the first case, auto takes an element by value, so the array decomposes into a pointer, and you cannot then iterate over a single pointer.

In the second case, you get a reference to an array, which you can, of course, iterate over.

+4
source

std::begin and std::end do not have overloads for pointer types. Range-based cycles are defined to use these functions. If you want to prevent the array from being converted to a pointer, you can bind the link to the array.

Β§8.5.3

5 A reference to type β€œcv1 T1 ” is initialized by an expression of type β€œcv2 T2 ” as follows:

- If the link is an lvalue reference and an initializer Expression

is an lvalue (but not a bit field), and "cv1 T1 " is a link compatible with "cv2 T2 ," or

- has a class type (i.e. T2 is a class type), where T1 not a link associated with T2 , and can be implicitly converted to an lvalue of type "cv3 T3 ", where "cv1 T1 " is a link compatible with "cv3 T3 " 106 (this conversion is selected by listing the applicable conversion functions (13.3.1.6) and choosing the best one due to overload resolution (13.3)),

then the link is bound to the lvalue initializer expression in the first case and the result of the lvalue conversion to the second case (or, in any case, to the corresponding base class by the object subobject). [Note: the usual value of lvalue-to-rvalue (4.1), (4.2) and the standard pointer function (4.3) do not need conversions and, therefore, are suppressed when direct bindings to lvalues ​​are performed. - final note]

Since the second marker point is not applied, the link refers directly to the array and no conversion occurs.

0
source

Source: https://habr.com/ru/post/1209078/


All Articles