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
string
in 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.