opSlice and foreach with ranges

Ali Çehreli acehreli at yahoo.com
Thu Feb 17 12:17:38 PST 2011


Is that not implemented yet?

TDPL mentions a very useful feature on page 381 under "12.9.1 foreach 
with Iteration Primitives".

(Note: I am copying all of this manually; the typos are mine):

It first shows a function that includes a possible "compiler rewrite" of 
a foreach loop:

void process(SimpleList!int lst) {
     for (auto __c = lst; !__c.empty; __c.popFront()) {
         auto value = __c.front;
         ... // Use value of type int
     }
}

It then says

<quote>
... if the iterated object offers the slice operator with no arguments 
lst[], __c is initialized with lst[] instead of lst. This is in order to 
allow "extracting" the iteration means out of a container without 
requiring the container to define the three iteration primitives.
</quote>

I couldn't get that to work with the following code:

import std.stdio;

struct MyRange
{
     int theOnlyOne;

     @property bool empty() const
     {
         return false;
     }

     @property ref int front()
     {
         return theOnlyOne;
     }

     void popFront()
     {}
}

struct MyCollection
{
     MyRange opSlice() const
     {
         return MyRange();
     }
}

void main()
{
     auto coll = MyCollection();

     foreach (i; coll) {            // <-- compilation error
         // ...
     }
}

Error: cannot infer type for i

Providing the type of i as 'int' or 'ref int' produce a different error:

     foreach (int i; coll) {

or

     foreach (ref int i; coll) {

produce

Error: no property 'opApply' for type 'MyCollection'

Please note that taking a slice explicitly works:

     foreach (i; coll[]) {

but not the feature mentioned in TDPL.

Thank you,
Ali


More information about the Digitalmars-d-learn mailing list