Definition of "OutputRange" insuficient

monarch_dodra monarchdodra at gmail.com
Tue Jul 17 08:36:44 PDT 2012


> OutputRange is designed for infinite output ranges, like output 
> files and appender.
>
> [snip]

Well, "designed" is open for interpretation.

Yes, all (most) "ranges defined as output" (files, streams, 
appenders) are infinite, and don't define empty (or define it as 
false).

But that does not mean that all ranges that fulfill 
"isOutputRange" are infinite. By leaving out the "empty" 
requirement from output range, we are forcing the infinity 
concept on anything that wishes to use the output facilities of a 
range.

On Tuesday, 17 July 2012 at 14:53:00 UTC, Andrei Alexandrescu 
wrote:
> Actually if you look at put() it's designed to accept an input 
> range with assignable elements, in which case it assigns to the 
> front and moves forward. But I agree we could improve output 
> ranges with a notion of "full". The paradox is, for an input 
> range used for output, "full" is a synonym for "empty" :o).
>
> Andrei

Well, the "underlying" container being full makes the range 
empty. I don't really see how we could have a notion of a "full 
range". But I'll admit the contrast if funny to observe :D

Regarding put, I noticed that actually. I was going to propose 
using it in "copy", as it could probably improve performance in 
the "generic case" (that, and it is _meant_ to be used that way). 
Right now, it defines a "genericImplementation" as:

--------
     static Range2 genericImpl(Range1 source, Range2 target)
     {
         for (; !source.empty; source.popFront())
         {
             put(target, source.front);
         }

         return target;
     }
--------
which should really just be
--------
     static Range2 genericImpl(Range1 source, Range2 target)
     {
         put(target, source);
         return target;
     }
--------
In the case of "fill" is that "put" will throw an exception if 
source does fit into target. There is no real way to know this 
before hand either, and it is not possible to just insert until 
full: That is the entire problem.

An easy fix at this point would be to just provide "hasEmpty", 
no? After all, we have "hasLength". That said, I feel this is 
more a bandage, and that outputRange really should define empty.

--------
On a same note, I just noticed that "forwardRange" does not have 
to adhere to the "outputRange" concept. This is in stark 
opposition to the classification in C++. Is this on purpose? I 
took it for granted that "forward" meant "output"+"input"+"save", 
but it is really just "input"+"save".

In theory, this means that the only "safe" way to write to a 
range would be to use "put".

There is a "hasAssignableElements" trait, but the requirements 
are odd:
1) It requires the range to be at least "forward", meaning an 
inputRange or an outputRange (!) will fail the 
"hasAssignableElements" test.
2) It only checks that "front" is assignable, so that does not 
guarantee you can assign to the indexes of a RandomAccess range :/



More information about the Digitalmars-d mailing list