What ever happened to move semantics?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Wed Feb 28 22:01:59 UTC 2024


On Wednesday, February 28, 2024 7:17:44 AM MST Timon Gehr via Digitalmars-d 
wrote:
> > A Move Constructor is a struct member constructor that moves, rather than
> > copies, the argument corresponding to its first parameter into the object
> > to be constructed. The argument is invalid after this move, and is not
> > destructed.
> >
> > A Move Constructor for struct S is declared as:
> >
> > ```d
> > this(S s) { ... }
> > ```
>
> This is a breaking language change.
>
> Also, consider
>
> ```d
> struct S{
>      ...
>      this(T)(T t){ ... }
>      ...
> }
> ```
>
> This constructor will be a move constructor iff T=S. Therefore, that the
> destructor is not called on the argument in some cases may be very
> surprising to programmers.

I've already run into issues trying to add copy constructors at work where
code broke because it had declared

this(T)(T t) { ...}

and that then conflicted with a copy constructor which was automatically
added when I added a copy constructor to the type of one its member
variables. Fortunately, the result was a compiler error, and I could then
add a template constraint to avoid having the templated constructor take the
type that it was constructing, but the risks with something like this
suddenly being turned into a move constructor certainly should be
considered.

In some cases, such constructors likely work just fine when given a variable
of the type that they're constructing, whereas in others, they're probably
never actually used that way and wouldn't compile if you tried. So, if such
a constructor became a move constructor, a type that was perfectly moveable
before could become an error to try to move - or do something that is very
much not a move if the constructor happens to compile when given a variable
of the type that it's constructing, but it does something rather different
from a move.

Of course, to an extent, the same could be said of

    this(S s) { ... }

though I would guess that in most cases, having that turned into a move
constructor would work, whereas a templated constructor would be much more
likely to not work with the type being constructed.

Another idea here would be that if we required something like an attribute
on the constructor - e.g. @movecons - then the compiler could not only see
that you intended to make it a move constructor, but it could give you an
error if it didn't have the appropriate signature. I'm not sure that we
really want to go that route, but if we did require an attribute, at least
we wouldn't accidentally have existing constructors turn into move
constructors - and having the compiler verify for you that it's treating it
as a move constructor could be valuable.

> 4. Regarding `nothrow` on Move Constructors and Move Assignment Operators.
>
> > The Move Constructor is always nothrow, even if nothrow is not explicitly
> > specified. A Move Constructor that throws is illegal.
> This special case should be motivated in the DIP. I assume the
> motivation is that because the argument is not destructed, throwing is
> particularly error-prone here.
>
> In general, I would advise against built-in requirements on specified
> attributes unless absolutely necessary.

Yeah. I don't know if it ever makes sense for move constructors to throw
(e.g. arguably it shouldn't be allowed destructors to throw, though IIRC, it
is currently allowed). That being said, IMHO, we should be absolutely
minimizing how much we require _any_ kind of function attribute. It causes
all kinds of trouble for code that doesn't want to (or can't) use them.

At least with nothrow, you can do something like catch the exception and
then assert false, but IMHO, in general, core language functionality should
not require specific attributes.

As it is, I'm having quite a bit of trouble with copy constructors and
attribute requirements (e.g. getting compilation errors with regards to
druntime code that insists on pure), and I need to put together some bug
reports on it.

Attributes can be great in theory, but they simply don't work in many cases
with complex code.

- Jonathan M Davis





More information about the Digitalmars-d mailing list