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