<div dir="ltr"><div>Are there any known solutions to perform efficient move construction in D?</div><div><br></div><div>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.</div><div><br></div><div>Consider this C++; really bad example, but just to illustrate:</div><div><br></div><div>struct X { std::string s; };</div><div><br></div><div>struct Y {</div><div>  std::string s;<br></div><div><br></div><div>  this(const X &x)<br>  {</div><div>    s = s; // copy the string, expensive</div><div>  }</div><div>  this(X &&x)<br>  {</div><div>    s = std::move(s); // claim s from x, efficient</div><div>  }</div><div>};</div><div><br></div><div>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...</div><div><br></div><div><br></div><div>I'm thinking in D, this *might* be possible:</div><div><br></div><div>struct X {}<br><br>struct Y {</div><div>  this(auto ref X x)</div><div>  {</div><div>    static if (__traits(isRef, x))</div><div>    {</div><div>      // x is lvalue, copy construct</div><div>    }</div><div>    else</div><div>    {</div><div>      // x MUST be rvalue(?), move construct</div><div>      // does this pattern require that I invalidate x the same way C++ does such that X's destructor won't clean up or crash?</div><div>    }</div><div>  }</div><div>}</div><div><br></div><div><br></div><div>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.</div><div><br></div><div>Assuming this does work, the next issue is something that mirrors std::move(), is there already such a thing?</div><div><br></div><div><br></div><div>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.</div><div>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:</div><div><br></div><div><div>struct X {}<br><br>struct Y {</div><div>  this(ref const X x)</div><div>  {</div><div>    // x is lvalue reference, copy construct<br></div><div>  }<br></div><div><div>  this(X x)</div></div><div>  {</div><div>    // x is an lvalue... which may be a copy of another lvalue. can't move construct :/</div><div>  }</div><div>}</div></div><div><br></div><div>I guess the question in this case is how overload selection may or may not work...</div><div>I didn't test this, but I expect it's an ambiguous call given an lvalue?</div><div><br></div><div>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.</div><div><br></div><div><br></div><div>Where is this stuff at?</div><div><br></div><div><br></div><div>- Manu</div><div></div></div>