endless loop with ref and non-ref parameter

Era Scarecrow rtcvb32 at yahoo.com
Thu Jan 24 21:43:46 PST 2013


On Friday, 25 January 2013 at 04:26:18 UTC, Jonathan M Davis 
wrote:
> With templated code, it can be important. But then again, if 
> there's no point in having a non-const overload, you can simply 
> not declare any overloads without const. You only run into 
> problems when you mix const and non-const.
>
> The compiler has to be able to deal with various combinations 
> of const and ref regardless of what it actually makes sense to 
> declare. The only way that I can think of to get rid of that 
> problem is to make it illegal to declare both const and 
> non-const overloads at the same time, which seems unnecessarily 
> restrictive (especially with regards to generic code), even if 
> it doesn't normally make sense to overload on const.

  True, but still it seems overtly annoying. I noticed most of 
this from TDPL. pg 257

[quote]
   The problem is that opAssign as defined expects a ref Widget, 
that is, an lvalue of type Widget. To accept assignment from 
rvalue in addition to lvalues, Widget must define two assignment 
operators:

   import std.algorithm;

   struct Widget {
     private int[] array;
     ref Widget opAssign(ref Widget rhs) {
       array = rhs.array.dup;
       return this;
     }
     ref Widget opAssign(Widget rhs) {
       swap(array, rhs.array);
       return this;
     }
   }

  There's no more .dup in the version takint an rvalue. Why? Well 
the rvalue (with it's array in tow) is practically owned by the 
second opAssign: It was copied prior to entering the function and 
will be destroyed just before the function returns. This means 
there's no more need to duplicate rhs.array because nobody will 
miss it. Swapping rhs.array with this.array is enough. When 
opAssign returns, rhs goes away with this's old array, and this 
stays with rhs's old array--perfect conservation of state.

  We now could remove the first overload of opAssign altogether: 
The one taking rhs by value takes care of everything (lvalues are 
automatically converted to rvalues). But keeping the lvalue 
version allows for a useful optimization: instead of .duping the 
source, opAssign can check whether the current array has space 
for accommodating the new contents, in which case an overwrite is 
enough.
[/quote]

  The whole time I look at the example code, I can see how the ref 
Widget can be const and continue to work perfectly, but the 
non-ref cannot be const (without ugly unsafe casting). But if you 
try to pass const data to opAssign it will either try to copy it 
(if it's POD or postblit it), or fail outright. In my mind I 
shouldn't have to double the functions to have it 'do the right 
thing', even if it's just to forward them. This is not a case 
where 'auto ref' could help, as lvalue/rvalue distinction needs 
to be kept.


More information about the Digitalmars-d-learn mailing list