move semantics are a mess

Manu turkeyman at gmail.com
Mon May 27 21:08:00 UTC 2019


On Mon, May 27, 2019 at 6:56 AM Atila Neves via Digitalmars-d
<digitalmars-d at puremagic.com> wrote:
>
> On Sunday, 26 May 2019 at 18:24:17 UTC, Manu wrote:
>
> <snip>
> > I tried to correct those issues by adding the appropriate
> > `forward!args` in the right places, but that causes chaos.
> >
> > One serious issue I've noticed looks like this:
> >   void fun(Args...)(auto ref Args args)
> >   {
> >     auto b = T(forward!args);
> >   }
> >
> >   fun(myT.move); // <- call with rvalue; move semantics desired
> >
> > I've encountered various forms of this general pattern. So the
> > trouble
> > here is, it tried to call a T constructor with `args`, and
> > there are
> > cases:
> >   1. args are actual constructor args -> call appropriate
> > constructor
> >   2. args is a T lvalue -> call the copy constructor
> >   3. args is a T rvalue -> `b` should be move initialised, but
> > you get
> > a compile error because it tries to pass an rvalue to the copy
> > constructor which strictly reveices a ref arg, and that call is
> > invalid.
>
> This is indeed problematic.
>
> > It leads to this:
> >
> > struct S
> > {
> >   this(ref inout(S) copyFrom) inout {} // <- copy ctor
> >   this(S moveFrom) { this = moveFrom.move; } // <- !!! some
> > kind of
> > move constructor?
> > }
>
> Unfortunately that doesn't even work - the way you wrote it above
> leads to a crash due to infinite recursion

Haha, truefacts. I just typed that in the email to make the point. The
code I actually wrote uses `moveFrom.moveEmplace(this)`, which didn't
trigger recursion (because memcpy).
It's all rubbish though!

Even if this stuff worked, the sequence of memcpy's and memset's from
construction to emplacement is extremely lame! Calling a function like
`emplace` introduces at least 2 unnecessary memcpy's, `forward`
introduces another at each callsite, and then if you are authoring a
utility object, or a container, then there's at lest 1 additional
forwarding cycle for that layer... we'll easily land common cases
where move construction introduces 4-8 memcpy/memset's!

> > Move semantics effectively don't work. They're a gross hack at
> > best.
>
> I think the language definition on this needs to be precisely
> defined.

I think this should be D's next big top-priority ticket.
It's a gaping and embarrassing hole in D. It's another one of those
things that I couldn't show to my colleagues with a straight face and
expect them to take me (or D) seriously :/
I wonder if Andrei has room to consider this? He's probably the single
best person for the job...


More information about the Digitalmars-d mailing list