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&&
.
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_iterator
s to its contents. If you want to do a non-const
traversal over the contents, that won't help.
来源:https://stackoverflow.com/questions/13241108/why-does-a-range-based-for-statement-take-the-range-by-auto