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

Reply via email to