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

后端 未结 4 1082
春和景丽
春和景丽 2020-12-17 09:29

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

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

相关标签:
4条回答
  • 2020-12-17 09:37

    You may use:

    for (auto&& it : foo){
    
    }
    

    auto && is prefered to auto & to manage proxy iterator as for std::vector<bool>.

    0 讨论(0)
  • 2020-12-17 09:52

    In many ways this confusion is arising from the convention that's grown up over the years to bind a * or a & to the type as opposed to the variable.

    For example int* a is really int *a; i.e. a is a pointer to a value of type int.

    The same applies to references: in the case of int& a, a is a reference to a value of type int.

    So what you really want to do is write for (auto &it : foo) so it is a reference to the type inferred by auto. Then you can use it to manipulate the underlying vector elements. More often than not this will be written as

    for (auto& it : foo)

    Moving forward, you might want to use an r-value reference: for (auto&& it : foo) which is probably the best general form.

    0 讨论(0)
  • 2020-12-17 09:57

    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.

    0 讨论(0)
  • 2020-12-17 10:00

    I would use auto&&:

    for (auto&& it : foo) {
        // bla
    }
    

    The reason is spelt out in N3994 "Range-Based For-Loops: The Next Generation (Revision 1)" that it would better work with proxy objects (such as those coming from std::vector<bool>).

    In fact, that proposal for C++1z (supported already by Clang 3.5 SVN in -std=c++1z mode) proposes the syntax:

    // c++1z only
    for (it : foo) { 
        // bla
    }
    

    as a short-hand for for (auto&& it : foo).

    Update: the N3994 proposal was not voted into the C++17 working paper.

    0 讨论(0)
提交回复
热议问题