foreach over pointers OR foreach that mutates the iterator
Las via Digitalmars-d
digitalmars-d at puremagic.com
Wed Jan 25 08:15:49 PST 2017
So the reference says that (when range has the properties)
`foreach (e; range) { ... }` is equivalent to:
for (auto __r = range; !__r.empty; __r.popFront())
{
auto e = __r.front;
...
}
Though this isn't always true, as when I use this struct:
struct S {
int front = 10;
void popFront() {
--front;
}
@property bool empty() {
return front == 0;
}
}
then I can do this:
void main() {
S s;
auto p = &s;
p.popFront;
writeln(p.front);
}
But not this:
void main() {
S s;
auto p = &s;
foreach(i; p)
writeln(i);
}
x.d(18): Error: invalid foreach aggregate p
Failed: ["dmd", "-v", "-c",
"-of/tmp/.rdmd-1000/rdmd-x.d-032B33C4A922C519594F67AF08DBF6C9/objs/x.o", "x.d", "-I."]
Why should this work? Because some times I want foreach to modify
the iterator, because some times I like to have an inner foreach
that uses the same iterator as the outer one, to effectively
still iterate over the same range, but change the contents of the
loop.
Bad example:
foreach(i; &range) {
writeln(i);
if(i > 2) foreach(i; &range) {
writeln(i * 3);
if(i < 10)
break;
}
}
This loop would change behavior each time one of the 'if's pass.
An alternative would be to implement a new foreach, perhaps
&foreach, that does this instead:
for (/+ NB: We are not copying the range! +/; !range.empty;
range.popFront())
{
auto e = range.front;
...
}
Related:
UFCS does not work on pointers, which matters because of
std.range.primitives.
Thoughts?
More information about the Digitalmars-d
mailing list