<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 25 April 2017 at 14:17, Stanislav Blinov via Digitalmars-d <span dir="ltr"><<a href="mailto:digitalmars-d@puremagic.com" target="_blank">digitalmars-d@puremagic.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Tuesday, 25 April 2017 at 01:59:55 UTC, Manu wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Ah crap, I somehow missed the single-argument move() function.<br>
<br>
Okay, so this pattern is definitely reliable? I haven't seen it clearly documented anywhere that this is the prescribed pattern, and it's come up on stack overflow a few times, but it hasn't been answered correctly.<br>
I think this is poorly distributed knowledge.<br>
</blockquote>
<br></span>
It is definitely reliable.<span class=""><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
As Schveighoffer pointed out, this pattern requires *another* overload for `ref const X`? Surely if there is no `ref X` and only a `ref const X` available, it should choose that one rather than the byval one when the argument is not const (as demonstrated in the bug report?)<br>
</blockquote>
<br></span>
No, the bug report is incorrect. See <a href="http://dlang.org/spec/function.html#function-overloading" rel="noreferrer" target="_blank">http://dlang.org/spec/function<wbr>.html#function-overloading</a>. Remember that, unlike C++'s '&', "ref" is not a type, it's a parameter storage class. So, given the overloads<br>
<br>
foo(const ref X);<br>
foo(X x);<br>
<br>
or, more precisely:<br>
<br>
foo(ref const(X));<br>
foo(X x);<br>
<br>
if you call foo with a non-const X lvalue *or* rvalue, the second overload will be chosen (the exact match):<br>
<br>
X x;<br>
foo(x);   // typeof(x) == X, so foo(X) is chosen. It's passed by value, so x is copied first.<br>
foo(X()); // also calls foo(X), this time no copy is needed<br>
<br>
const X cx;<br>
foo(cx); // calls foo(ref const(X)), since typeof(cx) == const(X)<br>
<br>
In C++, those foos would be ambiguous. In D, they aren't, because it first checks whether it's const or not, and then whether it's an lvalue or an rvalue.<span class=""><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
It's demonstrated that `ref const X` might inhibit an efficient copy constructor implementation in some cases, but you can't have false-move's occurring when the lvalue is not const.<br>
</blockquote>
<br></span>
It's not about efficiency, it's about preserving type information. Once you slap "const" on, there's no getting rid of it without violating the type system.<br>
And there won't be any "false" moves. You either have a reference to copy from, or a full-blown copy/rvalue to move from.<br>
</blockquote></div><br></div><div class="gmail_extra">Right, yeah I see. So, basically, you admit that it is required to have 3 overloads; foo(X), foo(ref X) and foo(ref const X), in the event that I want to avoid needlessly copying X prior to constructing from it in the non-const case...</div><div class="gmail_extra">I can imagine in some cases, copy constructing from X, and making a copy of X then move constructing from X are similar/same cost... so it's really just a gotcha that authors need to be aware of.</div><div class="gmail_extra"><br></div><div class="gmail_extra">I feel this is complicated and there are a lot of particulars. This needs to be documented clearly in the language docs, and there should probably be some examples how it relates to C++'s copy/move construction offerings, because it's significantly different and anyone with C++ experience will fail to get this right.</div></div>