0

Недавно я пытался понять семантику перемещения и задал вопрос.Разница между std: forward forward

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

я реализовал первый вариант и проверяется, возвращает ли он л-значение или т-значение:

#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-значение), и если я могу это сделать:

&my_forward(int(5)); // r-value with int&& type 

Мой код не компилируется, потому что my_forward вернулся г-значение. В вопросе выше говорят, что разница между этой реализацией и стандартным (с std :: remove_reference и двумя разными аргументами с & и & & соответственно) заключается в том, что моя реализация постоянно возвращает l-значение, но, как я показал он возвращает как r-значение, так и l-значение.

Так что я удивляюсь, почему я не могу реализовать std :: forward вроде этого? В каких конкретных случаях он будет показывать разницу между стандартным? Кроме того, почему я должен указывать T как шаблон и не могу позволить ему определять себя с типом аргумента?

+0

Почему вы пытаетесь принять адрес ссылки RValue? – xinaiz

+0

@BlackMoses Чтобы проверить r-ценность. – LogicStuff

+0

@LogicStuff А, хорошо, подумал, что это неправильное представление об использовании '&' :) – xinaiz

ответ

3

Попробуйте hsing, как std вперед в реальном контексте. Твой не работает;

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, но forward перемещает ссылки rvalue с именами.

Rvalue ссылки с именами являются lvalues.

+0

Спасибо большое! Я проверил его с помощью этого [кода] (http://ideone.com/XPePam), и, похоже, я ошибся. Я не проверял его в реальном контексте, потому что я подумал (теоретически), что эти реализации были одинаковыми. Я не могу понять, в чем разница. Вы можете это объяснить? – fminkin

+0

И почему именно моя реализация работает так? Как мы видели в этой теме, он возвращает значение r, почему он не работает тогда? – fminkin

+0

** Ссылки на Rvalue с именами являются lvalues. ** Пока вы не поймете, что останетесь в замешательстве. – Yakk

1

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

  • Вы можете взять адрес glvalue, но не из prvalue , Значение gl представляет собой «местоположение» (то есть, где объект), prvalue представляет «инициализацию» (то есть какое значение имеет объект).

  • Вы можете украсть ресурсы из rvalue, но не из lvalue. Ссылки Lvalue привязываются к lvalues, ссылки rvalue привязываются к rvalues. Точка std::forward состоит в том, чтобы указать аргумент в значение r, когда было предоставлено значение r, и lvalue, когда было предоставлено lvalue.

Когда std::forward возвращает RValue, он фактически возвращает xvalue и xvalues ​​оба rvalues ​​и 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 
+0

Я думаю, вы имели в виду. «Вы можете украсть ресурсы из rvalue, но НЕ из lvalue». – Lenz

+0

@ Lenz: Я сделал, спасибо :-) –

Смежные вопросы