Когда дан код следующей структуры
template <typename... Args>
void foo(Args&&... args) { ... }
Я часто видел, как библиотечный код использует static_cast<Args&&>
внутри функции для пересылки аргументов. Как правило, это оправдывается тем, что использование static_cast
позволяет избежать ненужного создания экземпляра шаблона.
С учетом свертывания языковой ссылки и правил вывода шаблонов. Мы получаем идеальную пересылку с static_cast<Args&&>
, доказательство для этого утверждения ниже (в пределах полей ошибок, которые, я надеюсь, ответ просветит)
- Когда даны ссылки на rvalue (или для полноты - нет ссылки на квалификации, как в этом примере), это сворачивает ссылки таким образом, что результатом является rvalue. Используется правило
&& &&
→&&
(правило1
выше) - Когда даны ссылки на lvalue, это сворачивает ссылки таким образом, что результатом является lvalue. Здесь используется правило
& &&
→&
(правило2
выше)
По сути, это заставляет foo()
пересылать аргументы в bar()
в приведенном выше примере. Это поведение, которое вы получите при использовании std::forward<Args>
здесь.
Вопрос - зачем вообще использовать std::forward
в этих контекстах? Оправдывает ли отказ от дополнительной инстанциации нарушение соглашения?
В статье Говарда Хиннанта n2951 указано 6 ограничений, при которых любая реализация std::forward
должна вести себя "правильно". Это были
- Следует переслать lvalue как lvalue
- Следует переслать rvalue как rvalue
- Не следует пересылать значение как значение
- Должны пересылать менее квалифицированные cv выражения в более квалифицированные cv выражения
- Должен ли перенаправлять выражения производного типа в доступный однозначный базовый тип
- Не следует пересылать произвольные преобразования типов
(1) и (2) было доказано, что правильно работает со static_cast<Args&&>
выше. (3) - (6) здесь не применимы, потому что когда функции вызываются в выведенном контексте, ничего из этого не может произойти.
Примечание: я лично предпочитаю использовать std::forward
, но у меня есть оправдание только потому, что я предпочитаю придерживаться соглашения.