More C++0x - custom move()

N

Noah Roberts

I'm trying to understand the degredation principles behind references
and rvalue vs. lvalue, etc... As such I decided to implement my own
std::move() following this implementation:

http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-
features-in-vc10-part-2.aspx

Doesn't work. Apparently VC2010 RC implements the changes specified in
N2812:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2812.html#the-
problem

The issue I'm having here is that upon playing with this definition I
find that using the cast alone seems to work and I haven't been able to
find a way to break it:

template < typename T >
T&& my_move(T&& t)
{
return static_cast<T&&>(t);
}

My question then is why is it implemented in the standard in a more
complex manner using remove_reference<T>? I assume there's a very good
and important reason, so how do I break my_move?
 
B

Bo Persson

Noah said:
I'm trying to understand the degredation principles behind
references and rvalue vs. lvalue, etc... As such I decided to
implement my own std::move() following this implementation:

http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-
features-in-vc10-part-2.aspx

Doesn't work. Apparently VC2010 RC implements the changes
specified in N2812:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2812.html#the-
problem

Yes, the blog entry (and VC2010 Beta) is using "rvalues v1". The
Standard (and RC) is "rvalues v2".

http://blogs.msdn.com/vcblog/archive/2010/04/06/c-0x-core-language-features-in-vc10-the-table.aspx
The issue I'm having here is that upon playing with this definition
I find that using the cast alone seems to work and I haven't been
able to find a way to break it:

template < typename T >
T&& my_move(T&& t)
{
return static_cast<T&&>(t);
}

My question then is why is it implemented in the standard in a more
complex manner using remove_reference<T>? I assume there's a very
good and important reason, so how do I break my_move?

I think it makes a difference, if you are moving from a reference
(where T is U&).


Bo Persson
 
N

Noah Roberts

Yes, the blog entry (and VC2010 Beta) is using "rvalues v1". The
Standard (and RC) is "rvalues v2".

http://blogs.msdn.com/vcblog/archive/2010/04/06/c-0x-core-language-features-in-vc10-the-table.aspx

Thanks. I wasn't able to find that list, only for the beta and lower.
Looks like it has a couple additions as well.
I think it makes a difference, if you are moving from a reference
(where T is U&).

Yeah, I was confusing myself with some of my test code. I created a
function f(T&&) and tried to call it with the result of my_move on an
lvalue and it failed while std::move succeeds.
 
P

Paul Bibbings

Noah Roberts said:
The issue I'm having here is that upon playing with this definition I
find that using the cast alone seems to work and I haven't been able to
find a way to break it:

template < typename T >
T&& my_move(T&& t)
{
return static_cast<T&&>(t);
}

My question then is why is it implemented in the standard in a more
complex manner using remove_reference<T>? I assume there's a very good
and important reason, so how do I break my_move?

IIRC, the purpose of std::move is to convert to an rvalue. Your
implementation here doesn't achieve that. Called with:

struct X { /* ... */ };
X x;
my_move(x);

x is an lvalue, and so T resolves to X& and, through reference
collapsing, my_move becomes:

T& my_move(T& t)
{
return static_cast<T&>(t);
}

and you have forwarding, not moving.

As I see it, the very purpose of using remove_reference<T>::type in the
implemenations that I have seen is to prevent just this reference
collapsing in the return type.

Regards

Paul Bibbings
 
H

Howard Hinnant

<snip />






IIRC, the purpose of std::move is to convert to an rvalue.  Your
implementation here doesn't achieve that.  Called with:

   struct X { /* ... */ };
   X x;
   my_move(x);

x is an lvalue, and so T resolves to X& and, through reference
collapsing, my_move becomes:

  T& my_move(T& t)
  {
    return static_cast<T&>(t);
  }

and you have forwarding, not moving.

As I see it, the very purpose of using remove_reference<T>::type in the
implemenations that I have seen is to prevent just this reference
collapsing in the return type.

Paul is exactly correct.

I just wanted to add one more bit: Although there's nothing wrong
with writing my_move, especially for educational purposes, please
don't write move() and expect it to be called by other code (such as
the std::lib). move() is not a "customization point" like swap() is.
std::move() should do the right thing for every single type (even
yours) and so there is no motivation to customize it. I'm on a
crusade to make sure that when anyone wants to move something they
call std::move(x), not move(x). This frees up "move" to mean anything
you want in your namespace, without fear that it will be accidentally
called via ADL.

-Howard
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top