Bug 12109 – foreach with class alias this range iteration inconsistency
Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-02-08T10:28:00Z
Last change time
2014-02-08T10:45:58Z
Assigned to
nobody
Creator
peter.alexander.au
Comments
Comment #0 by peter.alexander.au — 2014-02-08T10:28:34Z
Sorry for the title, hard to explain in a few words:
class A
{
int[] a = [1, 2, 3];
alias a this;
}
void main()
{
import std.stdio, std.array;
auto a = new A();
while (!a.empty)
a.popFront();
writeln(a.a); // []
auto b = new A();
foreach (_; b)
{}
writeln(b.a); // [1, 2, 3]
}
The problem: iterating using popFront() manually gives a different result from using foreach. The foreach iteration doesn't consume the range, while the popFront/empty does. Presumably the foreach is making a copy of the aliased array and iterating that instead of the A object directly.
Expected: foreach should be consistent with using popFront/empty manually and should consume the range, i.e. the final writeln(b.a) should give []
It is very important that these are consistent otherwise algorithms that change from using popFront/empty to foreach will change behaviour when the user is using a class with alias this range. This may explain the variations seen in Issue 9506 between releases.
Comment #1 by jakobovrum — 2014-02-08T10:43:44Z
(In reply to comment #0)
> Sorry for the title, hard to explain in a few words:
This has nothing to do with AliasThis. All forward ranges behave this way with foreach (i.e. foreach operates on a `save`'d copy).
When `save` is not necessary (such as in algorithms that have already called `save`), a for-loop should be used, as seen in many places in Phobos.
Comment #2 by peter.alexander.au — 2014-02-08T10:45:58Z