Rvalue для перенаправления ссылок

Я читаю правила свертывания ссылок, и у меня возникает вопрос: почему, если я передаю rvalue A к

template<typename T>
void foo(T&&);

T выводится как A?

например. если перейти std::string() к функции T, выведено как std::string, почему бы не std::string&&? Для меня было бы более разумным, каково обоснование вывода T самому типу?

Ответ 1

Это просто соответствует тому, что мы ожидаем в целом от вычитания типа шаблона:

template <class T> void vfoo(T );
template <class T> void lfoo(T& );
template <class T> void cfoo(T const& );
template <class T> void ffoo(T&& );

std::string x;
vfoo(x);            // deduce T = std::string
lfoo(x);            // deduce T = std::string
cfoo(x);            // deduce T = std::string
ffoo(x);            // deduce T = std::string& !
ffoo(std::move(x)); // deduce T = std::string

Из оригинальной статьи, мой удар:

При выводе типа шаблона функции с использованием аргумента lvalue, совпадающего с ссылкой на rvalue, тип выводится как ссылочный тип lvalue. Когда вычитанию присваивается аргумент rvalue, вывод типа происходит так же, как и для других типов.

Это случай вывода lvalue, который является исключительным, поэтому он получает дополнительное предложение в правилах вывода типа. Случай rvalue типичен - он выстраивается в линию с простой ментальной моделью вставки в выведенных типах, чтобы увидеть, какую функцию вы оказываете. Вызывается T&& с помощью std::string? Получите T = std::string, чтобы аргумент читал std::string&&. Проверьте.

Ответ 2

Поскольку тип параметра функции имеет && на нем и вы выводите часть выражения "T".

Итак, "передача" std::string&& в T&& будет выводить T как std::string.

Подставляя std::string как T в выражение T&&, получаем std::string&&.

Это то же самое, что и вывод T в выражении T const&; когда "передано" a std::string по константной ссылке, часть T выводится как std::string.