Move Constructors - Converting Lvalues to Rvalues
Manu
turkeyman at gmail.com
Thu Oct 3 23:22:44 UTC 2024
On Fri, 4 Oct 2024 at 01:51, Walter Bright via Digitalmars-d <
digitalmars-d at puremagic.com> wrote:
> On 10/2/2024 4:17 PM, Manu wrote:
> > 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?
>
> My original plan was to do just that:
> ```
> S move(ref S s) => s;
> ```
> would be recognized and replaced with the `__lvalue(s)`. What bothered me
> about
> it was the magic behavior of it, such as what happens with:
> ```
> S move(ref S s, int i) => s;
> ```
> which will behave completely differently, and may be quite surprising to
> users.
> I expect somebody will inevitably set at store on:
>
> ```
> S move(ref S s) => s;
> S move(ref S s, int i) => s;
> ```
> doing the same thing, but they don't, and the user will be baffled and I
> will
> get bug reports and the language will become more complicated is in the
> ugly way
> C++ became.
>
Okay, fair. I'm convinced.
> '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...
>
> __rvalue() does nothing more than say its argument is not an lvalue, so it
> will
> not match with a `ref` parameter. Lifetime analysis occurs after overload
> resolution, so I don't think it will impact it.
>
> __rvalue() is not a move, it just guides the overload resolution to the
> move
> constructor/assignment. It's a hint.
>
Okay, so then from this perspective without any obvious place to pin any
lifetime tracking semantics, the lifetime of an argument to move will
continue after the call to move; which implies (as we discussed at some
length) that the callee MAY move the object, and if it does, the callee is
responsible for putting it back in an init state so that it is valid when
the calling object is destructed at some later time...
This is fine, and we tolerate this arrangement in C++ (probably for the
exact same reasons), but it's not quite an optimal solution. Sufficiently
capable lifetime tracking could theoretically elide calls to destructors
when it knows a move took place, but I can't see a way the calling scope
can have any such confidence with __rvalue() as a tool?
I guess this is where Timon's proposal for @move comes in. Incidentally,
that proposal seems to be additive to this work though; it could be added
later to give the calling scope that information, but it doesn't seem to
contradict your current path.
I think I'm satisfied with your direction.
It'd be interesting if you could push a working branch? I've been writing a
whole bunch of containers the last few days and I'd like to try it out if
it's in a testable state.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20241004/a2ada9eb/attachment.htm>
More information about the Digitalmars-d
mailing list