Search code examples
c++c++11move-semanticsstdlvalue-to-rvalue

Difference between std::forward implementation


Recently I've been trying to understand move semantics and came up with a question.

The question has already been discussed here.

I implemented the first variant and checked whether it returns l-value or r-value:

#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;
}

So if I pass l-value, it returns l-value (compiles, because I can take an adress from l-value) and if I do that:

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

My code doesn't compile, because my_forward returned r-value. In the question above they say that the difference between this implementation and standart one (with std::remove_reference and 2 different arguments with & and && respectively) is that my implementation returns l-value all the time, but as I've shown it returns both r-value and l-value.

So I wonder, why can't I implement std::forward like that? In what specific cases will it show difference between standart one? Also, why should I specify T as a template and can't let it define itself with argument type?


Solution

  • Try hsing it like std forward in a real context. Yours does not work;

    void test(std::vector<int>&&){}
    
    template<class T>
    void foo(T&&t){
      test(my_forward<T>(t));
    }
    
    foo( std::vector<int>{} );
    

    The above does not compile. It does with std::forward.

    Your forward does nothing useful other than block reference lifetime extension. Meanwhile, std::forward is a conditional std::move.

    Everything with a name is an lvalue, but forward moves rvalue references with names.

    Rvalue references with names are lvalues.