Почему ссылка Rvalue превращается в ссылку Lvalue универсальной ссылкой

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

#include <iostream>
#include <type_traits>
using namespace std;
template <typename T>
T f1(T&&t) {  //<-----this is a universal reference
cout << "is_lvalue reference:" << is_lvalue_reference<T>::value << endl;
cout << "is_rvalue reference:" << is_rvalue_reference<T>::value << endl;
cout << "is_reference:"        << is_reference<T>::value        << endl;
return t;
}
void f2(int&& t) {
cout << "f2 is_lvalue reference:" << is_lvalue_reference<decltype(t)>::value << endl;
cout << "f2 is_rvalue reference:" << is_rvalue_reference<decltype(t)>::value << endl;
cout << "f2 is_reference:" << is_reference<decltype(t)>::value << endl;
f1(t);

}

int main()
{
f2(5);
return 0;
}

И в GCC, и в VC ++ 2010 это результат:

f2 is_lvalue reference:0
f2 is_rvalue reference:1
f2 is_reference:1
is_lvalue reference:1
is_rvalue reference:0
is_reference:1

Другими словами, параметр t в f2 была ссылка на Rvalue, но при переходе к f1, параметр стал ссылкой на lvalue. Не должно ли это сохранить ценность в f1?

4

Решение

Причина в том, что именованные ссылки на rvalue обрабатываются как lvalue.

Вы должны использовать станд :: ход внутри f2 при прохождении T в f1 сохранить ценность:

void f2(int&& t) {
f1(std::move(t));
}

Вот Вы можете найти хорошее объяснение.

6

Другие решения

призвание f1(t)аргументом является выражение t, Не static_cast<decltype(t)>(t) или что-то. Ваше обследование decltype(t) не имеет ничего общего с призывом f1(t),

Выражение t имеет тип int и значение категории именующий. (Практическое правило заключается в том, что если вы можете взять адрес выражения, то это lvalue, и вы, безусловно, можете написать &t). «Информация» о том, что ссылочная переменная была первоначально объявлена ​​как ссылка, видна только через decltype экспертиза.

поскольку f1 называется с lvalue, T выводится int&,

NB. Вы возможно хотите f1 также использовать decltype(t) скорее, чем T, если вы когда-нибудь захотите увидеть is_rvalue_reference быть правдой в f1, Для аргументов rvalue, T выводит на не ссылочный тип, например если вы исправите f2 заставляя это делать f1(std::move(t)); затем f1«s T является int а также decltype(t) в f1 является int&&,

3

После изучения стандарта C ++ 11 у меня есть смутное представление о том, что происходит после моего f1(t); в f2, Я опишу это здесь, чтобы увидеть, правильно ли я понял:

  1. В f2, t является lvalue типа int&& (не intэто важное отличие)
  2. вызов f1(t); приводит к выводу типа следующим образом:

    2.1 когда T в f1 дается lvalue, выводится как ссылка на тип этого lvalue илиint&& &

    2.2 эталонные причины коллапса int&& & становиться int &, Это ценность T,

  3. Поскольку параметр f1 объявлен как T&&тип параметра t в f1 является int & &&, Таким образом, свертывание ссылок происходит во второй раз, чтобы определить тип t как int &,

  4. Следовательно, Т =int & и тип параметра t является int &, то есть параметр t является lvalue типа int &

Любой комментарий?

0
По вопросам рекламы [email protected]