DIP 1040

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Jul 18 22:09:58 UTC 2024


On Thursday, July 18, 2024 2:41:06 PM MDT Timon Gehr via Digitalmars-d wrote:
> On 7/18/24 22:27, Walter Bright wrote:
> > On 7/14/2024 3:51 AM, Timon Gehr wrote:
> >> - a parameter storage class that enforces the parameter was moved.
> >
> > The caller should make the decision of whether it's a move or a copy,
> > the callee should not care. The callee owns the value (and hence must
> > destruct it) in either case.
>
> It's simply that often, move is a better default than copy. This is
> because copies are silent, while use after move will give a diagnostic,
> forcing an explicit, and visible, opt into the less efficient semantics.
>
> Perhaps being able to change the default at the type level might be
> sufficient. I guess it can kind of be achieved with a private copy
> constructor.

Given that moving is generally more efficient, I would have thought that
what we would want to do is to always move if we can and copy if we can't -
which would mean that if we can guarantee that it's the last use of a
variable, we'd do a move; otherwise, it would be a copy.

A copy constructor then allows the programmer to override what happens with
a copy, and a move constructor allows the programmer to override what
happens with a move. If the programmer wants to prevent copying and/or
moving, then they @disable the corresponding constructor.

So, in any situation where the compiler can choose between a move and a copy
(e.g. when the variable is passed to a function by value, and it's clearly
the last use of that variable), what you get is

  1. If the value can be moved, it's moved.
  2. If the value can't be moved, but it can be copied, then it's copied.
  3. If the value can't be moved or copied, then it's an error.

Then in any situation where a copy is required, the type must support
copying, or you get an error. And in any situation where moving is required,
then the type must support moving, or it's an error.

And in any situation where the compiler has to do a copy, but the programmer
wants a move (e.g. because the programmer knows that it's actually the last
use of the variable, but the compiler doesn't know enough to guarantee
that), the programmer will have to use an explicit move (in which case, the
variable is set to the init value in case the programmer got it wrong, which
is what happens now).

So, that way, the programmer can control for a given type whether copies or
moves are done, and they'll get errors when the compiler can't make the code
work with the operations that the type supports.

Now, if you then have a type that's both copyable and moveable, and you want
to guarantee that a particular place uses a move, you're pretty much forced
to do an explicit move without us adding something akin to
pragma(inline, ...) for moves, but you can still force it with an explicit
move. Either way, I don't see why the callee would care whether a move had
occurred or not. The function is given a value, and it operates on it. It's
guaranteed to be owned by the function being called by virtue of the fact
that it's not passed by ref. It's the caller that's going to care whether a
move takes place, and that can be guaranteed by using an explicit move.

- Jonathan M Davis





More information about the Digitalmars-d mailing list