Input ranges do not compose

Sergey Gromov snake.scaly at gmail.com
Wed Dec 2 15:00:00 PST 2009


Say I want to present a file as an input range:

class RangeFile {
     bool empty() {...}
     ubyte front() {...}
     void popFront() {...}
     // some private stuff
}

I'm parsing it.  There are chunks, one byte for size then data of that size:

void parse(RangeFile rf) {
     while (!rf.empty) {
         int size = rf.front;
         rf.popFront();
         popFrontN(rf, size);
     }
}

It works.  Now let's do something useful with the chunks' contents. 
There are strings in there, byte for length, then that much characters. 
  Read 'em:

void parse(RangeFile rf) {
     while (!rf.empty) {
         int size = rf.front;
         rf.popFront();
         auto chunk = take(size, rf);
         while (!chunk.empty) {
             int len = chunk.front;
             chunk.popFront();
             auto str = new char[len];
             copy(take(len, chunk), str);
         }
     }
}

BANG.  This does not work.  The chunk won't end where it should.  The 
problem is that second take() creates a copy of the chunk data, and the 
copy() does not update chunk's remaining size while copying.

This behavior is fine and expected and desired for forward ranges and up 
but makes no sense for input ranges.

I thought I could fix it rewriting copy:

copy(take(len, &chunk), str);

But it didn't compile.  Told me something about something not being lvalue.

There are actually two issues:

1.  Most of the std.algorithm and std.range functions claim that they 
accept input ranges but take them *by value*.  This violates input 
ranges' non-copyable contract.

2.  A whole bunch of algorithms is required similar to those we have now 
but accepting their range arguments by reference and mutating them.

Do I miss something?  The ranges do not seem as universal to me anymore.



More information about the Digitalmars-d mailing list