Разница между реализацией std :: forward

Недавно я пытался понять семантику перемещения и задал вопрос.

Вопрос уже обсуждался Вот.

Я реализовал первый вариант и проверил, возвращает ли он 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 как шаблон и не могу позволить ему определять себя с типом аргумента?

0

Решение

Попробуйте использовать его как 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.

3

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

К сожалению, захват адреса не является полезной операцией в вашем контексте, потому что он смотрит на неправильный тип категории значений:

  • Вы можете взять адрес 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
1

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