<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 25 April 2017 at 08:46, Andrei Alexandrescu 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"><div class="HOEnZb"><div class="h5">On 04/24/2017 04:23 PM, ag0aep6g wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On 04/24/2017 08:48 PM, Stanislav Blinov wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Speaking of const violation and UB, std.algorithm.mutation.move seems to<br>
violate const without remorse:<br>
</blockquote>
<br>
Yup. Even in @safe code, which is a bug.<br>
<a href="https://issues.dlang.org/show_bug.cgi?id=15315" rel="noreferrer" target="_blank">https://issues.dlang.org/show_<wbr>bug.cgi?id=15315</a><br>
</blockquote>
<br></div></div>
Should fail in all situations, thanks for reporting.<br>
<br>
The original code should work like this:<br>
<br>
struct X {}<br>
<br>
struct Y {<br>
  private X _x;<br>
  this()(auto ref X x)<br>
  {<br>
    static if (__traits(isRef, x))<br>
    {<br>
        _x = x;<br>
    }<br>
    else<br>
    {<br>
        import std.algorithm.mutation : move;<br>
        _x = move(x);<br>
    }<br>
  }<br>
}<br>
<br>
Note how I made the ctor templated so it accepts auto ref. The less sophisticated version is simply:<br>
<br>
struct X {}<br>
<br>
struct Y {<br>
  private X _x;<br>
  this(ref X x)<br>
  {<br>
     _x = x;<br>
  }<br>
  this(X x)<br>
  {<br>
     import std.algorithm.mutation : move;<br>
     _x = move(x);<br>
  }<br>
}<br></blockquote><div><br></div><div>Ah crap, I somehow missed the single-argument move() function.</div><div><br></div><div>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.</div><div>I think this is poorly distributed knowledge.</div><div><br></div><div>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?)</div><div>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.</div></div></div></div>