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.