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