Perfect forwarding
Вопрос
Что такое perfect forwarding? Объясните forwarding-ссылки, схлопывание ссылок и std::forward на примере фабрики.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Задача: передать аргументы дальше, сохранив категорию и константность
Forwarding-ссылка `T&&` с выводимым T
Вывод T как U& для lvalue и схлопывание ссылок
`std::forward<T>` условно приводит к rvalue
Примеры: make_unique, emplace_back, std::invoke-обёртки
Ловушки: перегрузка с forwarding-ссылкой перехватывает слишком много, forward дважды
Что могут спросить следом
- Почему нельзя дважды вызвать std::forward на одном аргументе?
- Почему конструктор с forwarding-ссылкой опасен рядом с копирующим конструктором?
Разбор
Perfect forwarding решает задачу обёртки: принять аргументы любого вида и передать их дальше ровно такими же, lvalue как lvalue, rvalue как rvalue, сохранив const. Для этого параметр объявляют T&&, где T выводится, это forwarding-ссылка. Если передали lvalue типа U, T выводится как U&, и U& && по правилу схлопывания даёт U&. Если rvalue, T = U и параметр U&&. Внутри функции параметр всё равно lvalue, потому что у него есть имя, и std::forward<T>(x) возвращает его в исходной категории: при T = U& это lvalue, при T = U это static_cast<U&&>. Так устроены std::make_unique<T>(std::forward<Args>(args)...) и emplace_back. Ловушки: после std::forward rvalue-аргумент может быть уже перемещён, поэтому дважды его форвардить нельзя; шаблонный конструктор с forwarding-ссылкой выигрывает перегрузку у копирующего конструктора для неконстантного lvalue, его ограничивают концептами или enable_if.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Предыдущий вопрос
Что выведет: forwarding и перегрузка по категории
Следующий вопрос
Схлопывание ссылок
Ещё по теме «Move-семантика»
- Перенос между складами: map::extract без копий
- Топ участников: сортировка записей без копий строк
- lvalue, prvalue, xvalue
- std::move от const-объекта
- push_back и emplace_back
- std::exchange в перемещении
- Объясни move-семантику
- Допишите обёртку с perfect forwarding