Почему оператор, основанный на диапазоне, принимает диапазон с помощью auto &&?
Оператор for
, основанный на диапазоне, определен в п. 6.5.5, чтобы быть эквивалентным:
{
auto && __range = range-init;
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin ) {
for-range-declaration = *__begin;
statement
}
}
где range-init
определяется для двух форм основанного на диапазоне for
как:
for ( for-range-declaration : expression ) => ( expression )
for ( for-range-declaration : braced-init-list ) => braced-init-list
(предложение дополнительно указывает значение других подвыражений)
Почему __range
задан выведенный тип auto&&
? Мое понимание auto&&
заключается в том, что оно полезно для сохранения исходной ценности (lvalue/rvalue) выражения, передавая ее через std::forward
. Однако __range
не проходит через std::forward
. Он используется только при получении итераторов диапазона, как один из __range
, __range.begin()
или begin(__range)
.
Какая польза от использования "универсальной ссылки" auto&&
? Не было бы auto&
?
Примечание. Насколько я могу судить, предложение ничего не говорит о выборе auto&&
.
Ответы
Ответ 1
Не было бы auto & хватает?
Нет, не будет. Это не позволило бы использовать выражение r-value, которое вычисляет диапазон. auto&&
используется, потому что он может связываться с выражением l-value или выражением r-value. Поэтому вам не нужно вставлять диапазон в переменную, чтобы она работала.
Или, иначе говоря, это было бы невозможно:
for(const auto &v : std::vector<int>{1, 43, 5, 2, 4})
{
}
Не было бы const auto&
?
Нет, не будет. A const std::vector
возвращает только const_iterator
в его содержимое. Если вы хотите выполнить обход не const
по содержимому, это не поможет.