opApply with/without ref
H. S. Teoh
hsteoh at quickfur.ath.cx
Thu Jan 12 19:49:49 PST 2012
Hi all,
I'm experimenting with overloading foreach() with opApply, and I found
that this code doesn't compile:
class C {
void opApply(int delegate(uint n) cb) const {
...
}
}
unittest {
auto c = new C;
foreach (n; c) {
...
}
}
I get this error:
Error: function intset.intset.opApply (int delegate(uint n) cb) is not
callable using argument types (int delegate(ref uint __applyArg0) @safe)
Eventually I found out that it's because the argument to the delegate
must be a ref, that is, opApply must be modified to read:
void opApply(int delegate(ref uint n) cb) const {
...
}
This appears to be the case whether or not I write foreach(n; C) or
foreach(ref n; C). My question is, is this a compiler bug, or is this
intentional in the language? If the latter, why?
More to the point, I'm implementing a class which stores a set of
unsigned numbers in a compact form; I wrote an opApply() method to make
it easy to iterate over. However, the compact representation doesn't
allow arbitrary mutation to set elements. That is, the following is not
allowed:
foreach (ref n; c) {
n++;
}
The problem is that this code compiles just fine, because there's no way
to say that opApply is only allowed for non-ref indices, but that it
doesn't do what it appears to say. The collection c is unchanged because
opApply() calls the delegate with a local variable: the number itself is
not actually stored in the data structure, so opApply() computes it
on-the-fly and hands it to the delegate. So modifying n in the foreach
body doesn't actually update the structure, even though it appears to.
How can I specify that only non-ref foreach loops are allowed for this
class? I thought that declaring opApply() the way I did at first (i.e.,
without the ref argument) is the correct way, but obviously the compiler
doesn't like it. (FWIW, I'm using GDC, I don't know if dmd has the same
behaviour.)
T
--
Lottery: tax on the stupid. -- Slashdotter
More information about the Digitalmars-d-learn
mailing list