called copy constructor in foreach with ref on Range

Stanislav Blinov stanislav.blinov at gmail.com
Tue Jun 23 03:25:55 UTC 2020


On Tuesday, 23 June 2020 at 02:41:55 UTC, Jonathan M Davis wrote:

> As things stand, uncopyable ranges aren't really a thing, and 
> common range idiomns rely on ranges being copyable.

Which idioms are those? I mean, genuine idioms, not design flaws 
like e.g. references.

> We'd need some major redesigning to make uncopyable ranges 
> work, and personally, I don't think that it's worth the trouble.

Of course we would. Andrei is entertaining changing the whole 
input range API. Though he, like you, seems opposed to the idea 
of uncopyables.

> The range API has no requirement that the init value of a range 
> be empty, and any generic code which relies on such behavior is 
> buggy. In the case of classes, it would outright crash, because 
> the init value would be null.

Yeah, that's a shame.

> I agree that ideally the range API would require that the init 
> state of a range be a valid, empty range, but that's simply not 
> how it works right now. In order to make it work that way, we'd 
> have to redesign the range API in at least some respects (e.g. 
> getting rid of save and making it illegal for classes to be 
> forward ranges).

Better yet - making it illegal for classes to be ranges.

> As things stand, it is _not_ true that it's safe to copy 
> forward ranges and then use the original. Sure, it will work 
> for some ranges, but for others it won't. The entire reason 
> that save exists is for ranges that are classes, because 
> copying them does not result in an independent range. The range 
> API does not require that copying a range result in an 
> independent copy. It's not even guaranteed that copying a range 
> that's a struct will result in an indpendent copy. Depending on 
> the range type, copying it could result in an independent copy, 
> or it could result in a reference to to the original range, or 
> it could even result in part of the state being copied and part 
> of it being a reference (e.g. if the current front is stored 
> directly in the range, but the iteration state is stored by 
> reference).

If copying isn't making a copy, it's not copying.

> If you rely on copying a range resulting in an independent 
> copy, you will have buggy code - even if it's a forward range. 
> The _only_ way that the range API specifies that you can get an 
> independent copy of a range is to use save, and generic code 
> should never rely on any other mechanism for that.

That's exactly what I said. "Copying of forward ranges is 
absolutely fine. It's what the current `save()` primitive is 
supposed to do."
...Except, of course, that that shouldn't be the case. *Copying* 
should be creating a copy. :)

> Now, ideally, we'd get rid of save and require that copying a 
> forward range result in an independent copy (which would then 
> require that a class be wrapped in a struct to be a range)

Yes!

> but that's simply not how the current range API works.

No, it's not :(


More information about the Digitalmars-d-learn mailing list