Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The only difference between <code>ref</code> and <code>const ref</code> is that <code>const ref</code> is <code>const</code> and <code>ref</code> is not. Both must take a variable. Neither can take a temporary. This is different from C++ where <code>const T&amp;</code> will take any value of type <code>T</code> - including temporaries.</p> <p><code>opBinary</code> cannot return either <code>ref</code> or <code>const ref</code>, because there's no variable to return. It's creating a temporary. The same goes for <code>Create</code>. And creating a local variable with the value that you want to return doesn't help either, because you can't return a reference to a local variable. It would end up referring to a variable which didn't exist anymore.</p> <p>What you need to do here is add another overload of <code>opEquals</code>:</p> <pre><code>bool opEquals(CustomReal x) const { return value == x.value; // just for fun } </code></pre> <p>With that, your code will compile.</p> <p>I would point out though that the current situation with <code>opEquals</code> <em>does</em> need to be ironed out a bit. You'll notice that if you only have the overload for <code>opEquals</code> that I gave you and not the one that you currently have, the code fails to compile, and you get an error similar to this:</p> <pre><code>prog.d(15): Error: function prog.CustomReal.opEquals type signature should be const bool(ref const(CustomReal)) not const bool(CustomReal x) </code></pre> <p>The compiler is currently overly picky about the exact signature of <code>opEquals</code> for structs (a few other functions - such as <code>toString</code> - have similar issues). It's a known issue and will probably be resolved in the near future. However, for now, just declare both overloads of <code>opEquals</code>. If you compare a <code>CustomReal</code> with a variable, then the <code>const ref</code> version will be used, and if you compare a <code>CustomReal</code> with a temporary, then the other version will be used. But if you have both, you should be okay.</p> <p>Now, why</p> <pre><code>assert(a == CustomReal(123.123456)); </code></pre> <p>works, and</p> <pre><code>assert(a == Create()); </code></pre> <p>doesn't, I'm not sure. I'd actually expect <em>both</em> of them to fail, given that <code>const ref</code> can't take a temporary, but for some reason, the compiler accepts it here - it probably has to do with how it treats <code>opEquals</code> special. Regardless, as I said, there are some issues with <code>opEquals</code> and structs which need to be ironed out, and hopefully that'll happen soon. But in the meantime, declaring both overloads of <code>opEquals</code> seems to do the trick.</p> <p><strong>EDIT:</strong> It appears that the reason that</p> <pre><code>assert(a == CustomReal(123.123456)); </code></pre> <p>works, and</p> <pre><code>assert(a == Create()); </code></pre> <p>doesn't is because of the fact (for reasons that I don't understand) a struct literal is considered an lvalue, whereas the return value of a function which is not <code>ref</code> is (unsurprisingly) an rvalue. There are a <a href="http://d.puremagic.com/issues/show_bug.cgi?id=5889" rel="nofollow">couple</a> of <a href="http://d.puremagic.com/issues/show_bug.cgi?id=3659" rel="nofollow">bug reports</a> related to it, arguing that struct literals should be rvalues, but apparently they're lvalues by design (which baffles me). In any case, that's why a function which takes <code>const ref</code> works with a struct literal but not with the return value of a function.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload