If I try to use std.algorithm.fill(Range1, Range2)(Range1 range, Range2 filler), I keep getting the error message that no template match could be found. It looks like the compiler is trying to match with fill (Range, Value) rather than the other one.
auto test = new char[256];
fill(test, "abc".dup);
Is it not possible to fill a character array using fill?
The error
test.d(13): Error: template std.algorithm.fill(Range,Value) if (isForwardRange!(Range) && is(typeof(range.front = filler))) does not match any function template declaration
test.d(13): Error: template std.algorithm.fill(Range,Value) if (isForwardRange!(Range) && is(typeof(range.front = filler))) cannot deduce t emplate function from argument types !()(char[],char[])
std.algorithm.fill
takes a range. All string types are ranges of dchar
. This is because they're all unicode. char
is a UTF-8 code unit wchar
is a UTF-16 code unit, and dchar
is a UTF-32 code unit. Multiple code units make up a code point, which is a character. For UTF-8, a code point could be up to 6 code units. For UTF-16, it could be up to 2. For UTF-32, 1 code unit is always 1 code point, so a dchar
is always guaranteed to be a valid character. char
and wchar
by themselves, however, are not guaranteed to be valid characters at all, and it's generally a bug if you see an individual char
or wchar
used. Multiple chars
or wchars
often must be combined to make up a single character. So, you can't deal with chars
or wchars
individually. That's why if you're iterating over a string of any kind with foreach, you should always give its type as dchar
.
foreach(dchar c; str)
...
If you didn't specify dchar
, then it would be whatever the character type of str
is, which would invariably cause bugs unless str
were an array of dchar
, because you'd end up with code units (pieces of characters) instead of code points (whole characters). Only dchars
can be dealt with individually.
It's because of all of this that all string types and character arrays are considered to be ranges of dchar
, regardless of what their actual element types are. So, when you call popFront
on a string, it could pop off a lot more than just one char
or wchar
. And if you call front
, it may have to decode multiple chars
or wchars
to return the dchar
that is the first character in the string. This means that you can't treat char
or wchar
arrays as being random access. The 4th character could be the 4th element, or it could be the 12th. And regardless of which index it starts at, it could be multiple code units long, so you can't just grab a random index in char
or wchar
array and expect it to be valid. So, arrays of char
and wchar
are not random access ranges. They're not output ranges either.
Think about it. Let's take the character '\U00010143'
(𐅃
) for instance. It has a code unit length of 4 for UTF-8 and 2 for UTF-16. You can't just fill any random char
or wchar
array with it. If it's a char
array, and its length isn't a multiple of 4, then the last (𐅃
) isn't going to fit. If it's a wchar
array, and its length isn't a multiple of 2, then it'll have the same problem. So, it really doesn't work to use a function like fill
on a char
or wchar
array.
Now, it'll work just fine with a dchar
array. Because a UTF-32 code unit is guaranteed to be a code point, every character in a dchar
array is one element, and it can be both a random access range and an output range. So, if you want to use a function like fill
with character arrays, you need to use an array of dchar
. You can use std.conv.to
to convert it to the type of character array that you want after that, but you can't fill an array of char
or wchar
directly.
Arrays of char
and wchar
work great with algorithms which don't need output ranges or random access ranges, but they don't work with those. For those, you need arrays of dchar
.
It might be a bug, but it's because typeof(test.front)
is dchar
, not char
, since it's interpreted as a UTF-8 string and it gives you the first Unicode character, rather than the first char
.
One of your import
s has probably either directly or indirectly imported a module like std.array
(or something of that sort), whose front()
function returns dchar
for char[]
. Try finding out which one it is, and instead of using that, do an import std.iterator
instead; that one returns char
instead of dchar
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With