On Wednesday, 25 August 2021 at 10:59:44 UTC, Steven
Schveighoffer wrote:
structs still provide a mechanism (postblit/copy ctor) to
properly save a forward range when copying, even if the guts
need copying (unlike classes). In general, I think it was a
mistake to use `.save` as the mechanism, as generally `.save`
is equivalent to copying, so nobody does it, and code works
fine for most ranges.
Consider a struct whose internal fields are just a pointer to its
"true" internal state. Does one have any right to assume that
the postblit/copy ctor would necessarily deep-copy that?
If that struct implements a forward range, though, and that
pointed-to state is mutated by iteration of the range, then it
would be reasonable to assume that the `save` method MUST
deep-copy it, because otherwise the forward-range property would
not be respected.
With that in mind, I am not sure it's reasonable to assume that
just because a struct implements a forward-range API, that
copying the struct instance is necessarily the same as saving the
range.
Indeed, IIRC quite a few Phobos library functions program
defensively against that difference by taking a `.save` copy of
their input before iterating over it.
What should have happened is that input-only ranges should not
have been copyable, and copying should have been the save
mechanism. Then it becomes way way more obvious what is
happening. Yes, this means forgoing classes as ranges.
I think there's a benefit of a method whose definition is
explicitly "If you call this, you will get a copy of the range
which will replay exactly the same results when iterating over
it". Just because the meaning of "copy" can be ambiguous,
whereas a promise about how iteration can be used is not.