Я предполагаю, что когда универсальный ссылочный параметр сопоставляется с ссылочным аргументом 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
?
Причина в том, что именованные ссылки на rvalue обрабатываются как lvalue.
Вы должны использовать станд :: ход внутри f2 при прохождении T в f1 сохранить ценность:
void f2(int&& t) {
f1(std::move(t));
}
Вот Вы можете найти хорошее объяснение.
призвание 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&&
,
После изучения стандарта C ++ 11 у меня есть смутное представление о том, что происходит после моего f1(t);
в f2
, Я опишу это здесь, чтобы увидеть, правильно ли я понял:
f2
, t
является lvalue типа int&&
(не int
это важное отличие) вызов f1(t);
приводит к выводу типа следующим образом:
2.1 когда T
в f1
дается lvalue, выводится как ссылка на тип этого lvalue илиint&& &
2.2 эталонные причины коллапса int&& &
становиться int &
, Это ценность T
,
Поскольку параметр f1
объявлен как T&&
тип параметра t
в f1
является int & &&
, Таким образом, свертывание ссылок происходит во второй раз, чтобы определить тип t
как int &
,
Следовательно, Т =int &
и тип параметра t
является int &
, то есть параметр t
является lvalue типа int &
Любой комментарий?