Using decodeFront with a generalised input range
Vinay Sajip
vinay_sajip at yahoo.co.uk
Fri Nov 9 10:45:49 UTC 2018
On Friday, 9 November 2018 at 10:26:46 UTC, Dennis wrote:
> On Friday, 9 November 2018 at 09:47:32 UTC, Vinay Sajip wrote:
>> std.utf.decodeFront(Flag useReplacementDchar =
>> No.useReplacementDchar, S)(ref S str) if (isInputRange!S &&
>> isSomeChar!(ElementType!S))
>
> This is the overload you want, let's check if it matches:
> ref S str - your InputRange can be passed by reference, but you
> specified S = dchar. S here is the type of the inputRange, and
> it is not of type dchar. It's best not to specify S so the
> compiler will infer it, range types can be very complicated.
> Once we fix that, let's look at the rest:
>
> isInputRange!S - S is an inputRange
> isSomeChar!(ElementType!S) - ElementType!S is ubyte, but
> isSomeChar!ubyte is not true.
>
> The function wants characters, but you give bytes. A quick fix
> would be to do:
> ```
> import std.algorithm: map;
> auto mapped = r.map!(x => cast(char) x);
> mapped.decodeFront!(No.useReplacementDchar)();
> ```
>
> But it may be better for somefn to accept an InputRange!(char)
> instead.
>
> Note that if you directly do:
> ```
> r.map!(x => cast(char)
> x).decodeFront!(No.useReplacementDchar)();
> ```
> It still won't work, since it wants `ref S str` and r.map!(...)
> is a temporary that can't be passed by reference.
>
> As you can see, ensuring template constraints can be really
> difficult. The error messages give little help here, so you
> have to manually check whether the conditions of the overload
> you want hold.
Thanks, that's helpful. My confusion seems due to my thinking
that a decoding operation converts (unsigned) bytes to chars,
which is not how the writers of std.utf seem to have thought of
it. As I see it, a ubyte 0x20 could be decoded to an ASCII char '
', and likewise to wchar or dchar. It doesn't (to me) make sense
to decode a char to a wchar or dchar. Anyway, you've shown me how
decodeFront can be used, so great!
Supplementary question: is an operation like r.map!(x =>
cast(char) x) effectively a run-time no-op and just to keep the
compiler happy, or does it actually result in code being
executed? I came across a similar issue with ranges recently
where the answer was to map immutable(byte) to byte in the same
way.
More information about the Digitalmars-d-learn
mailing list