Overhauling the notion of output range
Christian Kamm
kamm-incasoftware at removethis.de
Mon Jul 12 11:55:31 PDT 2010
Andrei Alexandrescu wrote:
> Yes. The point is that with a delegate you must choose between accepting
> E and E[]. Given the constraint, it's better for everyone to accept E[]
> and let put() take care of the occasional E by doing the wraparoo
> (&elem)[0..1].
I don't think the current implementation of put allows passing E and E[]
correctly:
void put(R, E)(ref R r, E e) if (isOutputRange!(R, E))
{
if (isArray!E && is(typeof(r(e))))
{
r(e);
}
else static if (is(typeof(r(new E[]))))
{
r((&e)[0 .. 1]);
}
else
{
static assert(false);
}
}
Example: typeof(fn) == void function(int[][]).
put(fn, int[]) -> ok
put(fn, int[][]) -> no match, isOutputRange!(fn, int[][]) fails.
You'll need a
void put(R, E)(ref R r, E[] a) if (isOutputRange!(R, E))
overload get the desired behavior.
Implementing that one generically also makes explicit what Steve was saying:
front-assignable ranges and classic output ranges are stuck using put with a
single element in a loop. Associating different performance tradeoffs with
abstractions that should be interchangeable sounds odd.
In the end it comes down to the question why R.put(E) and void R(E[]) should
both be output ranges for E. They should either take E or E[].
I'd go with void foo(E) being an output range for E and define the overloads
void put(ref R r, T t) if (isOutputRange!(R, T[])) // makes 1-element slice
void put(ref R r, E e) if (isOutputRange!(R, E))
void put(ref R r, A[] a) if (isOutputRange!(R, A)) // uses foreach
Christian
More information about the Digitalmars-d
mailing list