Не возвращайте `T&&`
Причина
Это означает возврат ссылки на уничтоженный временный объект. && — магнит для временных объектов.
Пример
Возвращаемая rvalue-ссылка выходит из области видимости в конце полного выражения, в которое она возвращается:
auto&& x = max(0, 1); // OK, пока
foo(x); // Неопределённое поведение
Такое использование — частый источник ошибок, которые нередко ошибочно приписываются компилятору. Разработчик функции должен избегать расстановки таких ловушек для пользователей.
Профиль безопасности времени жизни (когда будет полностью реализован) будет обнаруживать такие проблемы.
Пример
Возврат rvalue-ссылки допустим, когда ссылка на временный объект передаётся «вниз» к вызываемому; в этом случае гарантируется, что временный объект переживёт вызов функции (см. F.18 и F.19). Однако недопустимо передавать такую ссылку «вверх» к вызывающей области видимости большего размера. Для сквозных функций, принимающих параметры (обычной ссылкой или совершенной передачей) и желающих возвращать значения, используйте простой вывод типа возвращаемого значения auto (не auto&&).
Предположим, что F возвращает по значению:
template<class F>
auto&& wrapper(F f)
{
log_call(typeid(f)); // или какое-то другое логирование
return f(); // ПЛОХО: возвращает ссылку на временный объект
}
Лучше:
template<class F>
auto wrapper(F f)
{
log_call(typeid(f)); // или какое-то другое логирование
return f(); // OK
}
Исключение
std::move и std::forward возвращают &&, но они являются лишь приведениями типов — используемыми по соглашению только в контекстах выражений, где ссылка на временный объект передаётся в рамках того же выражения до уничтожения временного объекта. Нам не известны другие хорошие примеры возврата &&.
Контроль
Помечать любое использование && в качестве возвращаемого типа, кроме std::move и std::forward.