On 25 April 2017 at 14:17, Stanislav Blinov via Digitalmars-d < [email protected]> wrote:
> On Tuesday, 25 April 2017 at 01:59:55 UTC, Manu wrote: > > Ah crap, I somehow missed the single-argument move() function. >> >> 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. >> I think this is poorly distributed knowledge. >> > > It is definitely reliable. > > 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?) >> > > No, the bug report is incorrect. See http://dlang.org/spec/function > .html#function-overloading. Remember that, unlike C++'s '&', "ref" is not > a type, it's a parameter storage class. So, given the overloads > > foo(const ref X); > foo(X x); > > or, more precisely: > > foo(ref const(X)); > foo(X x); > > if you call foo with a non-const X lvalue *or* rvalue, the second overload > will be chosen (the exact match): > > X x; > foo(x); // typeof(x) == X, so foo(X) is chosen. It's passed by value, so > x is copied first. > foo(X()); // also calls foo(X), this time no copy is needed > > const X cx; > foo(cx); // calls foo(ref const(X)), since typeof(cx) == const(X) > > 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. > > 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. >> > > 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. > 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. > 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... 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. 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.
