On 4/30/20 2:03 PM, Casey wrote:
Interesting.  I'll take this into account.  I was putting the work into front because I didn't want to do the work until it was requested. Putting the work in popFront makes more sense in some ways, but the fact you have to call it before getting any records seems like it would break normal range algorithms.  (Please correct me if I'm wrong)  I'm wondering if putting the work into it's own method and calling it one from the constructor and from popFront the rest of the way.

You don't necessarily have to do it in a separate function, because until you return it from your factory method (the only way you can create such a thing), it technically doesn't need to be "sane".

So what I mean is at the bottom of your function you have:

auto readStream(Range)(auto ref Range r) if (isInputRange!(Unqual!Range))
{
   ... // define your struct

   auto result = StreamRange(r);
   if(!r.empty) result.popFront(); // prime range
   return result;
}

There is a valid argument to be made about not doing any work until requested. You could do this inside front, but in that case, I would say you have an additional boolean that checks if it has ever been run, and run popFront once (setting that bool to false). But I don't necessarily like that, because that puts an extra burden on front. front is supposed to be non-mutating, called as much as you need (ideally it should be inout). Practically, you can make it do work, but really the bulk of the work should be done in popFront.

Note that you will have to check for priming in popFront as well, because if you did for instance:

auto r = readStream(...);
r.popFront(); // skip first element?

This would not do what is expected. In fact, thinking about it some more, you should be able to call popFront as many times as you want and have it skip that many elements without calling front once. Your range will not do that.

-Steve

Reply via email to