Treating a slice as an InputRange

Jonathan M Davis newsgroup.d at jmdavisprog.com
Wed Nov 15 21:02:35 UTC 2017


On Wednesday, November 15, 2017 20:53:39 unleashy via Digitalmars-d-learn 
wrote:
> Hello,
>
> I'm writing a small parser for a specific binary format. The
> format is parsed by way of a sequence of functions, each
> deserializing a small portion of the format into a D type such as
> int, double, string, etc., operating on a single InputRange. The
> problem is, if I pass a slice to each of these functions, the
> slice doesn't get mutated by the popFront function used in the
> functions, so something like this:
>
> ubyte[] slice;
> ...
> int a = readInt(slice);
> double b = readDouble(slice);
>
> Ends up failing, because readInt properly reads an int, but the
> slice is not mutated "outside" of itself, which means readDouble
> will not read from where readInt stopped, and instead read from
> the start of the slice, and failing because there is an int
> encoded there and not a double. Both functions' signatures are
> like this:
>
> T readXXX(Range)(auto ref Range range) if (isInputRange!Range)
>
> So my question is, is there a way to treat a slice strictly as an
> InputRange, so that it is mutated no matter what? Or is there
> another way to do what I'm trying to do?
>
> I've worked around it using a "wrapper" InputRange struct, but I
> feel like there must be another way.

Typically, functions that operate on ranges either consume them, return a
new range that wrapped the one passed in, or return the original range with
some number of elements popped off. If you specifically want a function to
accept a range and mutate it without returning it, then it should take its
argument by ref. Having it take auto ref is actually quite odd, since that
means that the behavior can depend on whether an lvalue or rvalue is passed
in.

If you can't alter the function's signature, then you could always use
std.range.RefRange to wrap it, but it's better to change the function
signature if you can.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list