Move Constructors - Converting Lvalues to Rvalues
Manu
turkeyman at gmail.com
Wed Oct 2 23:17:37 UTC 2024
On Thu, 3 Oct 2024 at 04:06, Walter Bright via Digitalmars-d <
digitalmars-d at puremagic.com> wrote:
> On 10/1/2024 1:06 PM, Timon Gehr wrote:
> > I think in case we did go the function route, I think any implementation
> of
> > `move` that is much more complex than the following is a failure:
> >
> > ```d
> > auto move(T)(@moved T arg)=>arg;
> > ```
>
> The major difference between @move and __rvalue is the former is attached
> to the
> parameter, and the latter is attached to the argument. This might seem a
> distinction without a difference, but this has large implications with how
> overloading works.
>
> For example, how do we distinguish a move constructor from a copy
> constructor?
> ```
> this(ref S); // copy constructor
> this(S); // move constructor
> S s = t; // calls copy constructor (lvalue)
> S s = f(); // calls move constructor (rvalue)
> ```
> The current overloading rules work out of the box, an rvalue goes for the
> move
> constructor, and an lvalue goes to the copy constructor.
>
> The problem here is when I want to move t into s. How do I get it to call
> the
> move constructor?
> ```
> S move(ref S s) { return s; } // convert argument from lvalue to rvalue
> S s = move(t);
> ```
> This works, however, it creates a copy of s and then moves the copy! There
> needs
> to be a way to tell the compiler to use the move construct, hence:
> ```
> S s = __rvalue(t);
> ```
> All __rvalue does is flag the expression in ( ) as an rvalue. Then the
> rest of
> the semantics go from there. Note that a struct parameter with a move
> constructor will always pass by ref regardless, which is what we want
> here.
> Also, move semantics will only work on structs. Not classes, integers,
> pointers,
> arrays, etc. If move semantics are desired for them, they'll need to be
> wrapped
> in a struct, or use a template to wrap it for you.
>
> Consider:
> ```
> this(ref S); // copy constructor
> this(@move S); // move constructor
> ```
> I don't know how to make overloading work with this.
>
It's always some weird little detail that changes when I feel like we
discussed/designed a thing and then you implement it! :P
your __rvalue() is essentially the `T move(ref T)` intrinsic we discussed
at length; so why not just make the move intrinsic rather than this thing?
It seems trivial, but the reason I say this (as we discussed at length), is
that in addition to the trivial act of stripping away the ref to make it an
rvalue, the move expression will inevitably need to be enhanced with
lifetime tracking semantics. In the future, you will want to put logic in
that intrinsic to mark the end of lifetime of the memory region, and
possibly mark the transition of ownership for ownership tracking... 'move'
is the operation we seek, and it has lifetime related semantics involved
with the operation. __rvalue() doesn't feel like the right abstraction for
that set of semantics; you're gonna find yourself wondering where to pin
the lifetime semantics in the future...
Timon: Do you have any comment? Am I wrong?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20241003/53482ce7/attachment-0001.htm>
More information about the Digitalmars-d
mailing list