Какова цель перегрузки ссылки rvalue std::forward()?

Я экспериментирую с Perfect Forwarding и обнаружил, что std::forward() требуется две перегрузки:

Перегрузка №. 1:

template <typename T>
inline T&& forward(typename 
std::remove_reference<T>::type& t) noexcept
{
    return static_cast<T&&>(t);
}

Перегрузка №2:

template <typename T>
inline T&& forward(typename 
std::remove_reference<T>::type&& t) noexcept
{
    static_assert(!std::is_lvalue_reference<T>::value,
              "Can not forward an rvalue as an lvalue.");
    return static_cast<T&&>(t);
}

Теперь типичный сценарий для Perfect Forwarding выглядит примерно так:

template <typename T>
void wrapper(T&& e)
{
    wrapped(forward<T>(e));
}

Конечно, вы знаете, что когда создается экземпляр wrapper(), T зависит от того, является ли переданный ему аргумент lvalue или rvalue. Если это lvalue типа U, T выводится в U&. Если это rvalue, T выводится в U.

В любом случае - в рамках wrapper() - e является lvalue, поэтому всегда используется первая перегрузка std::forward().

Теперь мой вопрос:

Каков допустимый сценарий, в котором используется (и необходим) вторая перегрузка?

Этот язык сходит с ума.

Yves Daoust 29.05.2019 16:00

В случае, когда аргумент не является lvalue. Скажем, std::forward<int>(2).

Raymond Chen 29.05.2019 16:00

@Raymond Chen: конечно, но я не могу представить, когда такое использование необходимо

openyourmind 29.05.2019 16:18

Дайте определение «действительному сценарию». Мне кажется, что static_assert предназначен для предотвращения неправильного использования API, а не для покрытия «допустимого сценария».

Nicol Bolas 29.05.2019 16:30
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
16
4
612
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обоснование дизайна forward подробно обсуждается в N2951.

В этом документе изложены 6 вариантов использования:

A. Should forward an lvalue as an lvalue. All implementations pass this test. But this is not the classic perfect forwarding pattern. The purpose of this test is to show that implementation 2 fails in its stated goal of preventing all use cases except perfect forwarding.

B. Should forward an rvalue as an rvalue. Like use case A, this is an identity transformation and this presents a motivating example where the identity transformation is needed.

C. Should not forward an rvalue as an lvalue. This use case demonstrates a dangerous situation of accidentally creating a dangling reference.

D. Should forward less cv-qualified expressions to more cv-qualified expressions. A motivating use case involving the addition of const during the forward.

E. Should forward expressions of derived type to an accessible, unambiguous base type. A motivating use case involving forwarding a derived type to a base type.

F. Should not forward arbitrary type conversions. This use case demonstrates how arbitrary conversions within a forward lead to dangling reference run time errors.

Вторая перегрузка включает случаи B и C.

Далее в документе приводятся примеры каждого варианта использования, которые слишком длинны, чтобы повторять их здесь.

Обновлять

Я только что провел «решение» только первой перегрузки через эти 6 вариантов использования, и это упражнение показывает, что вторая перегрузка также включает вариант использования F: Не следует перенаправлять преобразования произвольного типа.

лол был на полпути к тому, чтобы напечатать ответ со ссылкой на эту статью - рад, что вы здесь :-)

Barry 29.05.2019 16:38

Другие вопросы по теме