27

A range-based for statement is defined in §6.5.4 to be equivalent to:

{ auto && __range = range-init; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } } 

where range-init is defined for the two forms of range-based for as:

for ( for-range-declaration : expression ) => ( expression ) for ( for-range-declaration : braced-init-list ) => braced-init-list 

(the clause further specifies the meaning of the other sub-expressions)

Why is __range given the deduced type auto&&? My understanding of auto&& is that it's useful for preserving the original valueness (lvalue/rvalue) of an expression by passing it through std::forward. However, __range isn't passed anywhere through std::forward. It's only used when getting the range iterators, as one of __range, __range.begin(), or begin(__range).

What's the benefit here of using the "universal reference" auto&&? Wouldn't auto& suffice?

Note: As far as I can tell, the proposal doesn't say anything about the choice of auto&&.

3
  • 1
    This way you can use r-values in the range. Commented Nov 5, 2012 at 22:06
  • "As far as I can tell, the proposal doesn't say anything about the choice of auto&&." And that proposal also uses the range library, which doesn't exist in C++11. Commented Nov 5, 2012 at 22:11
  • 2
    For future reference, the property of an expression described by e.g. 'lvalue' or 'rvalue' is its value category. Commented Nov 6, 2012 at 12:34

1 Answer 1

34

Wouldn't auto& suffice?

No, it wouldn't. It wouldn't allow the use of an r-value expression that computes a range. auto&& is used because it can bind to an l-value expression or an r-value expression. So you don't need to stick the range into a variable to make it work.

Or, to put it another way, this wouldn't be possible:

for(const auto &v : std::vector<int>{1, 43, 5, 2, 4}) { } 

Wouldn't const auto& suffice?

No, it wouldn't. A const std::vector will only ever return const_iterators to its contents. If you want to do a non-const traversal over the contents, that won't help.

Sign up to request clarification or add additional context in comments.

9 Comments

Oops, I actually meant to ask if const auto& would suffice. Won't this bind to anything too?
@sftrabbit: It won't bind to a non-const l-value. A const std::vector will only return const iterators.
Just to clarify: for (const auto& v : std::vector<int>{1, 43, 5, 2, 4}) {} is possible for a const traversal.
@fyzix: And what if it's not a temporary vector? See, you can't go changing the definition of range-based for based on whether the range is a temporary or not. So whatever you pick, const auto& or auto&& has to be the same in all cases. If you use const auto&, you can only ever have const iteration for all ranges. If you use auto&&, you can have whatever kind of iteration you want.
@starriet: The auto&& in question is built by the range-based for mechanism. If range-based for internally used auto&, the code you posted would not compile. It uses auto&& to allow that code to compile. That's the point of my answer.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.