I was trying to fix a few bugs in algorithm, as well as be more correct in template type specifiers, and I have to say: There is a serious restraint in the definition of an outputRange.

The current definition of "isOutputRange" is simply that "an output range is defined functionally as a range that supports the operation put".

The problem with this is this definition is not very useful (at all). Not just because it lacks front/popFront (this is actually OK). It is because it lacks an "empty". This makes it virtually un-useable unless you are blind writing to an infinite output range.

The proof that it is useless is that NOT A SINGLE ALGORITHM is compatible with output ranges. All algorithms that really only require an "output" systematically actually require "isForwardRange", or, worse yet "isInputRange" (!). This is only because they all make use of range.empty.

Here is an example of me trying to write "fill" respecting output range restrictions.

----
void fill(Range1, Range2)(Range1 range, Range2 filler)
if (isOutputRange!(Range1, ElementType!Range2) && isForwardRange!Range2)
{
    enforce(!filler.empty);
    auto t = filler.save;
    while (!range.empty) //Crud...
    {
        if (t.empty) t = filler.save;
        put(range, t.front);
        t.popFront();
    }
}
----
Almost... but no cookie.

If the argument against this is "but the output range "can't know if it empty"/"may never be empty", then is why we have an "isInfinite" definition... isn't it?

On the same note, why is the definitions of "inputRange" so divergent from outputRange. Shouldn't inputRange's definition mirror output's and be "supports get" (and "is empty")?

Shouldn't a correct "front/popFront" _only_ be required once we reach "forwardRange" and it's ability to save?

Here is an example of an implementation of fill, that only requires the filler to be an input range, if it has infinity.
----
void fill(Range1, Range2)(Range1 range, Range2 filler)
if (isOutputRange!(Range1, ElementType!Range2) && isInputRange!Range2
        && isInfinite!Range2)
{
    while( !range.empty )
    {
        put(range, get(filler));
    }
}
----

The current definition makes anything like near impossible.

Reply via email to