opApply ref and "const" iterators
Steven Schveighoffer
schveiguy at yahoo.com
Tue Sep 29 08:41:28 PDT 2009
On Mon, 28 Sep 2009 18:58:01 -0400, gzp <galap at freemail.hu> wrote:
> Hello,
>
> Iám new to D so i might be all wrong. Given the code:
>
> class Foo {
> int opApply( int delegate(ref real) dg ) {...} //A.
> int opApply( int delegate(real) dg ) {...} // B,
> }
>
> ...
> Foo foo = new Foo;
> foreach( a; foo ) {...} // 1.
> foreach( ref a; foo ) {...} // 2,
>
> Is it normal that, the A. version (with ref) is called for both cases
> and if the A is eliminated, only the 2. foreach loop will compile ? The
> second case works as i expected but what about the first case - the B.
> function won't be called ever ?
This is an undocumented limitation of the foreach/opApply model. Here is
what happens when you call foreach.
foreach(real x; foo)
{
writeln(x);
}
The compiler creates a local function with some internal name, like FE1,
then calls the opApply with that function. If you don't specify ref for
the args, it factors out the ref. For example:
int FE1(ref real _x)
{
auto x = _x; // auto generated code factors out reference
// now the foreach body goes here
writeln(x);
// auto-generated return
return 0;
}
// auto-generated call to opApply
foo.opApply(&FE1);
The factoring out of ref is to prevent you from having to write 2 delegate
functions if you want to handle both cases, since the non-ref version is
easy to implement in terms of the ref version. However, I think it is
useful to be able to limit the code from allowing ref.
See my already-reported enhancement for this issue:
http://d.puremagic.com/issues/show_bug.cgi?id=2443
>
> Furthermore, i wanted to create a const iterator
>
> class Foo {
> int opApply( int delegate(ref real) dg ) {...} //A.
> const int opApply( int delegate(real) dg ) {...} // B,
> }
>
> ...
> Foo foo = new Foo;
> const Foo f2 = foo;
> foreach( a; f2 ) {...} // 1.
> foreach( ref a; foo ) {...} // 2,
>
> It won't compile. (dmd 2.032) (I expected that, for the 1. loop the B
> version and for the 2. loop the A version of the functions'd be called)
>
> So what is the D way to create const iterator ?
There is definitely some room for improvement on const opApply.
http://d.puremagic.com/issues/show_bug.cgi?id=2442
I also have one other opApply enhancment which I think would help make
code much more readable:
http://d.puremagic.com/issues/show_bug.cgi?id=2498
Please vote for these issues so they are considered!
-Steve
More information about the Digitalmars-d
mailing list