Why move return an rvalue reference parameter need to wrap it with std::move()?
<p>I was reading Effective Modern C++ Item 25, on page 172, it has an example to demonstrate that, if you want to move return an rvalue reference parameter, you need to wrap it with std::move(param). As parameter by itself is always an lvalue, if no std::move(), it will be copy returned.</p>

<p>I don't understand. If std::move(param) merely cast the parameter it takes in into an rvalue reference, then what's the difference when param is already an rvalue reference?</p>

<p>Like in the code below:</p>

<pre><code>#include &lt;string&gt;
#include &lt;iostream&gt;
#include &lt;utility&gt;

template&lt;typename T&gt;
class TD;

class Widget {
public:
    explicit Widget(const std::string&amp; name) : name(name) {
        std::cout &lt;&lt; "Widget created with name: " &lt;&lt; name &lt;&lt; ".\n";
    }

    Widget(const Widget&amp; w) : name(w.name) {
        std::cout &lt;&lt; "Widget " &lt;&lt; name &lt;&lt; " just got copied.\n";
    }

    Widget(Widget&amp;&amp; w) : name(std::move(w.name)) {
        std::cout &lt;&lt; "Widget " &lt;&lt; name &lt;&lt; " just got moved.\n";
    }

private:
    std::string name;
};

Widget passThroughMove(Widget&amp;&amp; w) {
    // TD&lt;decltype(w)&gt; wType;
    // TD&lt;decltype(std::move(w))&gt; mwType;
    return std::move(w);
}

Widget passThrough(Widget&amp;&amp; w) {
    return w;
}

int main() {
    Widget w1("w1");
    Widget w2("w2");

    Widget wt1 = passThroughMove(std::move(w1));
    Widget wt2 = passThrough(std::move(w2));

    return 0;
}
</code></pre>

<p>It outputs:</p>

<pre><code>Widget created with name: w1.
Widget created with name: w2.
Widget w1 just got moved.
Widget w2 just got copied.
</code></pre>

<p>In passThroughMove(Widget&amp;&amp; w), w's type is already rvalue reference, std::move(w) just cast it into rvalue reference again. If I uncomment the TD lines, I can see that of decltype(w) and decltype(std::move(w)) are both Widget &amp;&amp;:</p>

<pre><code>move_parameter.cpp:27:21: error: implicit instantiation of undefined template 'TD&lt;Widget &amp;&amp;&gt;'
    TD&lt;decltype(w)&gt; wType;
                    ^
move_parameter.cpp:28:32: error: implicit instantiation of undefined template 'TD&lt;Widget &amp;&amp;&gt;'
    TD&lt;decltype(std::move(w))&gt; mwType;
                               ^
</code></pre>

<p>As both w and std::move(w) are same rvalue reference type, why "return std::move(w)" moves w, while "return w" only copy?</p>

<p>Edit: Thanks for the answers and comments. I got a better understanding now, but not sure if it's accurate. So std::move(w) returns an rvalue reference, just as w itself. But std::move(w) as a function call, it is an rvalue by itself, so it can be moved. While w as a named variable, it is an lvalue by itself, though the type of it is rvalue reference, so it cannot be moved.</p>