Диапазон для цикла с decltype (авто)

Есть ли ситуация, когда decltype(auto) будет лучшим выбором, чем auto (возможно, с &, && или cv квалификаторами) при использовании циклов, основанных на диапазонах? Другими словами, вы когда-нибудь пишете следующий код?

for (decltype(auto) item : range) {
    // ...
}

Ответы

Ответ 1

decltype(auto) генерирует другой тип, когда итератор ввода возвращается по значению. auto&& создает ссылку rvalue на временную, а decltype(auto) создает локальную копию (в С++ 17 она просто называет временную из-за гарантированного изменения разрешения).

Это мало чем отличается. В С++ 11/14 для него требуется переход ctor (который не вызывается на практике, но требуется) в случае decltype(auto), но не в С++ 17. В auto&& перемещение ctor не вызывается и не требуется.

Другим отличием является тип decltype(item), который всегда ссылается на auto&&, но в случае временного возвращаемого ввода iteraror decltype(item) является типом значения.

Вот об этом. На практике я не вижу причин для decltype(auto) над auto&&.

В стороне, auto& заставляет non-rvalue, const auto& заставляет non-mutable, а auto заставляет копию. Есть причины использовать auto&& вместо них, но это выходит за рамки этого вопроса. decltype(auto) ближе всего к auto&&, поэтому я сравнил эти два.

Ответ 2

Как упоминалось здесь:

decltype (auto) в первую очередь полезен для вывода возвращаемого типа функций пересылки и подобных оболочек

[...]

хотя его можно использовать для объявления локальных переменных, делая это, вероятно, просто антипаттерном, поскольку ссылка на локальные переменные не должна зависеть от выражения инициализации

Тем не менее, использование ссылки пересылки в цикле, основанной на диапазонах, является способом перехода.
Как упоминалось здесь:

Это безопасно и, по сути, предпочтительнее в общем коде, использовать вывод для пересылки ссылки

Я предлагаю этот вопрос о SO для получения дополнительной информации об использовании универсальной ссылки в цикле, основанном на диапазоне.