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 :(
