On Tuesday, 26 June 2012 at 06:05:49 UTC, Jonathan M Davis wrote:
If you can't calculate the length in O(1), then you're stuck
using walkLength,
which means iterating over the entire range to get its length.
And if that's
the case, then you can't make it a random access range, because
for it to be a
random access range, it either needs to have a length property
(which must be
O(1)) or be infinite. And I would fully expect for your code to
run into a
variety of bugs if you tried to claim that it was a length that
it wasn't
(e.g. ulong.max), since a number of functions will expect that
that's its
actual length and won't work properly if it's not.
For a range to be random access, it must fulfill these
requirements:
template isRandomAccessRange(R)
{
enum bool isRandomAccessRange = is(typeof(
(inout int _dummy=0)
{
static assert(isBidirectionalRange!R ||
isForwardRange!R && isInfinite!R);
R r = void;
auto e = r[1];
static assert(!isNarrowString!R);
static assert(hasLength!R || isInfinite!R);
}));
}
and I'm not sure that you can squeeze your range into that. You
could do it if
you just read in the entire range and created another range
from it (be it an
array or whatever), but you appear to be attempting something
which probably
won't quite work with the current range design. I suspect that
you'd do better
trying to claim that it wasn infinite rather than had a length,
but then you'd
have to be able to deal with the fact that empty is always
false.
- Jonathan M Davis
I actually only needed length() because random access ranges
required it (not because I did), but maybe I can avoid it some
way without using random access ranges at all... I'll try to
rework stuff. Thanks for the explanations.