I am trying to understand how std::move works and I bumped into some problems: so, this is the implementation:
template <typename T>
typename remove_reference<T>::type&& move(T&& t){
return static_cast<typename remove_reference::type&&>(t);
Let me go through this snippet line by line by using
string s2;
s2 = std::move(string("hello"));
- the constructor for the string hello is going to return an rvalue.
- type deduction rules tell us that if I am passing an rvalue to a parameter&& I get the referred type hence
stringin this case. - Now comes the static_cast part
remove_reference<T>is going to be simplyremove_reference<string>which is simplystring- What I don’t get is this type&& thing. I have seen already something like ::type but I don’t know if ::type&& makes a difference.
- So I am converting t whose type has been deduced to string (here could be my misunderstanding) to all this thing which seems to be just
string. I know that std::move needs to return an rvalue reference no matter if we pass an rvalue or an lvalue to it, i simply cannot get there. Could someone help?
CodePudding user response:
remove_reference<string> is NOT the same as just string. It is a struct that has a typedef type in its scope that is defined to string. So remove_reference<string>::type is string.
Thus remove_reference<string>::type&& is string&& which is an rvalue reference to string
A shorter way to write that would be remove_reference_t<string>&& (notice the _t)
CodePudding user response:
1 ~ 3 are correct. From 4,
remove_reference<string> is ..., remove_reference<string>, it's not string. remove_reference<string>::type is string. So remove_reference<string>::type&& is string&&, i.e. an rvalue-reference to string. Since the return type of std::move is rvalue-reference, std::move(...) leads to an xvalue:
The following expressions are xvalue expressions:
- a function call or an overloaded operator expression, whose return type is rvalue reference to object, such as
std::move(x);- ...
As the effect, std::move(string("hello")) is converting an prvalue string("hello") to xvalue, even both prvalue and xvalue are rvalues. std::move is supposed to be used to convert lvalue to rvalue, so the usage like this doesn't make much sense.
CodePudding user response:
It's not strictly relevant to the question, but good to know.
The type of t as a template parameter looks like a rvalue-reference, but may not be
template <typename T>
RetType fn(T&& t)
It's a special case, that says : "Use T&& or constT& as required"
See here for a better explanation than I could ever give
Edit: Actually, you need to know this to answer part 6 of your question.
