Move construction from !is(T == typeof(this))

Manu via Digitalmars-d digitalmars-d at puremagic.com
Sun Apr 23 21:21:36 PDT 2017


Are there any known solutions to perform efficient move construction in D?

D's pretty good at doing moves at all the right times, but with a serious
limitation compared to C++ that the type must be an exact match.

Consider this C++; really bad example, but just to illustrate:

struct X { std::string s; };

struct Y {
  std::string s;

  this(const X &x)
  {
    s = s; // copy the string, expensive
  }
  this(X &&x)
  {
    s = std::move(s); // claim s from x, efficient
  }
};

Now, I'm not saying that rval references are the only solution here, just
that I can overload the construction from an X for the rvalue and
non-rvalue case, which is what I want...


I'm thinking in D, this *might* be possible:

struct X {}

struct Y {
  this(auto ref X x)
  {
    static if (__traits(isRef, x))
    {
      // x is lvalue, copy construct
    }
    else
    {
      // x MUST be rvalue(?), move construct
      // does this pattern require that I invalidate x the same way C++
does such that X's destructor won't clean up or crash?
    }
  }
}


Is this solid? I have a vague memory of thinking on this once and realising
there was some edge case where it was logically flawed, but I can't
remember clearly.

Assuming this does work, the next issue is something that mirrors
std::move(), is there already such a thing?


Finally, a further problem exists with auto ref where the function must be
a template. I have cases of code-not-available lib API's where templates
are a problem.
I would prefer to overload 2 constructors for the 2 cases, than have one
template constructor and static if inside. I wonder what would happen in
this case:

struct X {}

struct Y {
  this(ref const X x)
  {
    // x is lvalue reference, copy construct
  }
  this(X x)
  {
    // x is an lvalue... which may be a copy of another lvalue. can't move
construct :/
  }
}

I guess the question in this case is how overload selection may or may not
work...
I didn't test this, but I expect it's an ambiguous call given an lvalue?

I wonder if this overload set could be made to work such that it is certain
that the non-ref overload is only called with rvalues; ie, given this
ambiguous call, ref is preferred for lvalues. rval can not call ref,
therefore must resolve to byval.


Where is this stuff at?


- Manu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20170424/e0b8551c/attachment.html>


More information about the Digitalmars-d mailing list