move semantics are a mess

Atila Neves atila.neves at gmail.com
Mon May 27 13:54:51 UTC 2019


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 (see code below) and 
swapping the order of the definitions of the "move" ctor with the 
copy one results in a compiler error message telling the user 
that you can't define both (the ordering thing is a bug since 
fixed).


Code:

-------------
import std.stdio;

struct Foo {
     this(int i) @safe {
         writeln("Foo int  ctor ", i);
     }
     this(ref const(Foo) other) @safe {
         writeln("Foo copy ctor");
     }
     this(Foo other) @safe {
         writeln("Foo move ctor");
     }
}


void fun(Args...)(auto ref Args args) {
     import std.functional;
     auto b = Foo(forward!args);
}


void main() {
     fun(77);
     auto f = Foo(33);
     fun(f);  // infinite recursion here
     // fun(Foo(42)); // doesn't compile with only the copy ctor 
defined
}
-------------

> 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.




More information about the Digitalmars-d mailing list