move semantic implementation

K

Krzysztof Poc

Hi

I have a question about move semantic implementation in g++.
I extracted the following code right from g++. I tested it and it
works
fine. Unfortunately I don't understand it.
I read that "move" may take both lvalue and rvalue. In the
implementation
below I can see that move may take rvalue only (_Tp&& as an argument).
On the
other hand when I tested
it I found that below move implementation may take both rvalue and
lvalue (as
written in a documentation). So
please explain me what is incorrect in my understanding.

Another thing that I don't understand is the trick with a
remove_reference.
I read in a documentation of move that it returns the rvalue. Keeping
in mind
that information I assumed that only the third definition of a
remove_reference
structure in a below example is required. Unfortunately it turns out
that all 3
implementations are required for the code to compile successfully.
Could you
please explain me why is that.

thanks in advance

template<typename _Tp>
struct remove_reference
{
typedef _Tp type;
};

template<typename _Tp>
struct remove_reference<_Tp&>
{
typedef _Tp type;
};

template<typename _Tp>
struct remove_reference<_Tp&&>
{
typedef _Tp type;
};

template<typename _Tp>
inline typename remove_reference<_Tp>::type&&
move(_Tp&& __t)
{
return __t;
}
 
S

SG

[...]
I read that "move" may take both lvalue and rvalue. In the
implementation below I can see that move may take rvalue
only (_Tp&& as an argument). On the other hand when I tested
it I found that below move implementation may take both rvalue
and lvalue (as written in a documentation). So please explain
me what is incorrect in my understanding.

Another thing that I don't understand is the trick with a
remove_reference. I read in a documentation of move that it
returns the rvalue. Keeping in mind that information I assumed
that only the third definition of a remove_reference structure
in a below example is required. Unfortunately it turns out
that all 3 implementations are required for the code to
compile successfully. Could you please explain me why is that.

Both things are closely related, actually.
template<typename _Tp>
inline typename remove_reference<_Tp>::type&&
move(_Tp&& __t)
{
  return __t;
}

This is not valid C++11. You probably have an old GCC/libstdc++
version. To make it compile under C++11 you have to replace "return
__t;" with "return static_cast<typename
remove_reference<_Tp>::type&&>(__t);".

As for your questions: There is a thing called reference collapsing:

T T&& T&
------------------
int int&& int&
int&& int&& int&
int& int& int&
^^^^

So, you can't be sure that T&& is actually an rvalue reference type.
It might be an lvalue reference type depending on T. T&& is an lvalue
reference type when T is an lvalue reference type.

Then, there is a special template argument deduction rule. If your
function template takes a parameter of type T&& and T is to be
deduced, T will be deduced to be an lvalue reference type if you pass
an lvalue to the function:

template<class T>
void foo(T&& p);

int main() {
int i=0;
foo(i+0); // --> T=int, T&&=int&&
foo(i); // --> T=int&, T&&=int&
}

So, you see that foo also accepts lvalues. The nice thing about it is
that the "valueness" of the argument is encoded in T so that it can be
restored with something like std::forward<T>(p). That's how perfect
forwarding is implemented.

Back to move:

template<typename _Tp>
inline typename remove_reference<_Tp>::type&&
move(_Tp&& __t)

If you invoke move with an lvalue of type std::string, _Tp will be
deduced to be std::string& which makes decltype(__t) to be
std::string& as well. But std::move is supposed to always return
unnamed rvalue references. That means _Tp&& would be the wrong return
type. We have to remove any "&" from _Tp first. This is done via
remove_reference<_Tp>::type.

Cheers!
SG
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top