called copy constructor in foreach with ref on Range

Jonathan M Davis newsgroup.d at jmdavisprog.com
Tue Jun 23 03:52:23 UTC 2020


On Monday, June 22, 2020 9:25:55 PM MDT Stanislav Blinov via Digitalmars-d-
learn wrote:
> 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.

It is extremely common to wrap ranges in other ranges (and in fact, you
basically have to in order to have lazy ranges). That really doesn't work
very well - if at all - if you can't copy the range. It might be possible
with a bunch of explicit calls to move, but that would result in range-based
code in general being @system without a clean way to use @trusted, since
whether it's really safe to mark such moves with @trusted would depend on
the specific range implementation, which then is a big problem with generic
code. Regardless of whether it's actually possible to make it work though,
it's a complete mess in comparison to simply copying. And the fact that
chaining range-based calls is extremely common makes the problem that much
worse.

The way that ranges are routinely passed around and wrapped works as well as
it does, because ranges are copyable.

> > 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.

The semantics of copying a variable or object vary wildly depending on the
type regardless of whether we're talking about ranges. Copying a pointer or
reference is still a copy even if it isn't a deep copy. Copying a range
_always_ results in a copy, just like it does with any other type. It just
doesn't necessarily result in a copy which can be independently iterated.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list