On Tuesday, 24 August 2021 at 09:15:23 UTC, bauss wrote:

A range should be a struct always and thus its state is copied when the foreach loop is created.

Actually the range contracts don't mention that it needs to be a by value type. It can also be a reference type, i.e. a class.


Which means the state resets every time the loop is initiated.

True for any forward range and above, not true for input ranges. The problem with them is that some of them are structs, and even if they are not forward ranges they do have this behavior due to implicit copy on assignment, which can potentially make the code confusing.

If your range uses some internal state that isn't able to be copied then or your ranges are not structs then your ranges are inherently incorrect.

If we follow the definition of ranges, they must not be copy-able at all. The only way to copy/save, would be to have .save method and call that method. This again is not being properly followed by even phobos implementations.

Note, that a better approach would be to replace .save in definition of forward range with a copy constructor, then all non-compliant ranges would become suddenly compliant, while those that have .save method should be refactored to a copy constructor version.


This is what a foreach loop on a range actually compiles to:

```d
for (auto copy = range; !copy.empty; copy.popFront())
{
    ...
}
```

You should add .save on assignment if range is a forward range, or just remove the assignment if it is not.

Best regards,
Alexandru.


Reply via email to