Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forcing auto to be a reference type in a range for loop

Tags:

Suppose I have foo which is a populated std::vector<double>.

I need to operate on the elements of this vector. I'm motivated to write

for (auto it : foo){    /*ToDo - Operate on 'it'*/ } 

But it appears that this will not write back to foo since it is a value type: a deep copy of the vector element has been taken.

Can I give some guidance to auto to make it a reference type? Then I could operate directly on it.

I suspect I'm missing some trivial syntax.

like image 745
P45 Imminent Avatar asked Aug 06 '14 11:08

P45 Imminent


People also ask

What does auto do in a for loop?

Range-based for loop in C++ Often the auto keyword is used to automatically identify the type of elements in range-expression.

How does range-based for loop work in C++?

C++11 introduced the ranged for loop. This for loop is specifically used with collections such as arrays and vectors. Here, the ranged for loop iterates the array num from beginning to end. The int variable var stores the value of the array element in each iteration.

How do you use a range-based loop?

Use the range-based for statement to construct loops that must execute through a range, which is defined as anything that you can iterate through—for example, std::vector , or any other C++ Standard Library sequence whose range is defined by a begin() and end() .

Is there range-based for loop in C?

Range-based for loop (since C++11) Executes a for loop over a range. Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container.


1 Answers

A minimal auto reference

The loop can be declared as follows:

for (auto& it : foo) {    //    ^ the additional & is needed    /*ToDo - Operate on 'it'*/ } 

This will allow it to be a reference to each element in foo.

There is some debate as to the "canonical form" of these loops, but the auto& should do the trick in this case.

General auto reference

In a more general sense (outside the specifics of the container), the following loop works (and may well be preferable).

for (auto&& it : container) {    //    ^ && used here } 

The auto&& allows for bindings to lvalues and rvalues. When used in a generic or general (e.g. template situation) this form may strike the desired balance (i.e. references, copies, prvalue/xvalue returns (e.g. proxy objects) etc.).

Favour the general auto&&, but if you have to be specific about the form, then use a more specific variation (e.g. auto, auto const& etc.).

Why is auto&& better?

As noted in other answers here and the comments. Why is auto&& better? Simply it will do what you think it should in most cases, see this proposal and its update.

As always, Scott Meyers' blog about this also makes for a good read.

like image 63
Niall Avatar answered Nov 09 '22 16:11

Niall