Trying to alias this a grapheme range + making it a forward range
ag0aep6g
anonymous at example.com
Mon Jul 8 23:01:49 UTC 2019
On 08.07.19 23:55, aliak wrote:
> struct ustring {
> string data;
> this(string data) {
> this.data = data;
> }
> auto get() {
> static struct Range {
> typeof(string.init.byGrapheme) source;
> bool empty() { return source.empty; }
> void popFront() { source.popFront; }
> auto front() { return source.front[]; }
> auto save() { return this; };
> }
> return Range(this.data.byGrapheme);
> }
> alias get this;
> }
>
> But I keep on ending up with a UTFException: "Encoding an invalid code
> point in UTF-8" with code like:
>
> writeln("hello".ustring);
`source.front` is a temporary `Grapheme` and you're calling `opSlice` on
it. The documentation for `Grapheme.opSlice` warns: "Invalidates when
this Grapheme leaves the scope, attempts to use it then would lead to
memory corruption." [1]
So you can't return `source.front[]` from your `front`. You'll have to
store the current `front` in your struct, I guess.
Also, returning a fresh range on every `alias this` call is asking for
trouble. This is an infinite loop:
auto u = "hello".ustring;
while (!u.empty) u.popFront();
because `u.empty` and `u.popFront` are called on fresh, non-empty,
independent ranges.
> Problem 2:
>
> How can I get the aliased ustring type to behave as a ForwardRange? If I
> add the save method to the voldermort range type, the
> isForwardRange!ustring fails because the requirement on isForwardRange
> checks to see if save returns the same type it's called on. Which is not
> the case here since typeof(ustring.save) == ustring.get.Range). But
> nontheless does have a save method.
You must provide a `save` that returns a `ustring`. There's no way
around it.
Maybe make `ustring` itself the range. In the code you've shown, the
`alias this` only seems to make everything more complicated. But you
might have good reasons for it, of course.
By the way, your're not calling `source.save` in `Range.save`. You're
just copying `source`. I don't know if that's effectively the same, and
even if it is, I'd advise to call `.save` explicitly. Better safe than
sorry.
[1] https://dlang.org/phobos/std_uni.html#.Grapheme.opSlice
More information about the Digitalmars-d-learn
mailing list