Недавно я пытался понять семантику перемещения и задал вопрос.
Вопрос уже обсуждался Вот.
Я реализовал первый вариант и проверил, возвращает ли он l-значение или r-значение:
#include <iostream>
using namespace std;
template <typename T>
T&& my_forward(T&& x) {
return static_cast<T&&> (x);
}
int main() {
int a = 5;
&my_forward(a); // l-value
return 0;
}
Поэтому, если я передаю l-значение, он возвращает l-значение (компилируется, потому что я могу взять адрес из l-значения), и если я это сделаю:
&my_forward(int(5)); // r-value with int&& type
Мой код не компилируется, потому что my_forward вернул r-значение. В вопросе выше они говорят, что разница между этой реализацией и стандартной (с std :: remove_reference и 2 разными аргументами с & а также && соответственно) моя реализация всегда возвращает l-значение, но, как я показал, она возвращает и r-значение, и l-значение.
Поэтому мне интересно, почему я не могу реализовать std :: forward таким образом? В каких конкретных случаях он будет отличаться от стандартного? Кроме того, почему я должен указать T как шаблон и не могу позволить ему определять себя с типом аргумента?
Попробуйте использовать его как std forward в реальном контексте. У тебя не работает;
void test(std::vector<int>&&){}
template<class T>
void foo(T&&t){
test(my_forward<T>(t));
}
foo( std::vector<int>{} );
Выше не компилируется. Это с std::forward
,
Ваш форвард не делает ничего полезного, кроме продления срока действия ссылки на блок. В то же время, std::forward
является условным std::move
,
Все с именем является lvalue, но вперед перемещает rvalue ссылки с именами.
Rvalue ссылки с именами являются lvalues.
К сожалению, захват адреса не является полезной операцией в вашем контексте, потому что он смотрит на неправильный тип категории значений:
Вы можете взять адрес glvalue, но не prvalue. Значение glvalue представляет «местоположение» (то есть, где находится объект), значение prvalue представляет «инициализацию» (т.е. какое значение имеет объект).
Вы можете красть ресурсы из значения, но не из значения. Ссылки Lvalue связываются с lvalues, ссылки rvalue связываются с rvalue. Точка std::forward
должен приводить аргумент к rvalue, когда было предоставлено rvalue, и к lvalue, когда было предоставлено lvalue.
когда std::forward
возвращает значение rvalue, фактически оно возвращает значение xvalue, а значения xvalue являются одновременно значениями rvalue и glvalues:
lvalue f() for "T& f();", decltype(f()) is T&
/
glvalue
/ \
value xvalue f() for "T&& f();", decltype(f()) is T&&
\ /
rvalue
\
prvalue f() for "T f();", decltype(f()) is T