called copy constructor in foreach with ref on Range

Stanislav Blinov stanislav.blinov at gmail.com
Mon Jun 22 21:11:07 UTC 2020


On Monday, 22 June 2020 at 20:51:37 UTC, Jonathan M Davis wrote:

> You're unlikely to find much range-based code that does that 
> and there really isn't much point in doing that. Again, copying 
> isn't the problem. It's using the original after making the 
> copy that's the problem.

Copy *is* the problem. If you can't make a copy (i.e. you get a 
compilation error) - you don't have a problem, the compiler just 
found a bug for you. Sadly, historically D's libraries were built 
around lots of redundant copying, even though there are very few 
cases where copies are actually required. The reason why we're 
"unlikely to find much range-based code that does that [move]" is 
(a) sloppy or shortsighted design and (b) poor language support. 
The latter hopefully stands to change.

> And moving doesn't fix anything, since the original variable is 
> still there
> (just in its init state, which would still be invalid to use in 
> generic code and could outright crash in some cases if you 
> tried to use it - e.g. if it were a class reference, since it 
> would then be null).

Eh? A range in 'init' state should be an empty range. If you get 
a crash from that then there's a bug in that range's 
implementation, not in user code.

> So, code that does a move could accidentally use the original 
> range after the move and have bugs just like code that copies 
> the range has bugs if the original is used after the copy has 
> been made. So, the rule of thumb is not that you should avoid 
> copying ranges. It's that once you've copied a range, you 
> should then use only the copy and not the original.

That is not true. Copying of forward ranges is absolutely fine. 
It's what the current `save()` primitive is supposed to do. It's 
the copying of input ranges should just be rejected, statically.


More information about the Digitalmars-d-learn mailing list