std.algorithm.fill
занимает диапазон. Все строковые типы имеют диапазон dchar
. Это потому что они все в юникоде. char
- это кодовая единица UTF-8 wchar
- это кодовая единица UTF-16, а dchar
- это кодовая единица UTF-32. Несколько единиц кода составляют кодовую точку, которая является символом. Для UTF-8 кодовая точка может составлять до 6 кодовых единиц. Для UTF-16 это может быть до 2. Для UTF-32 1 кодовая единица всегда равна 1 кодовой точке, поэтому всегда гарантируется, что dchar
будет действительным символом. char
и wchar
сами по себе, однако, не гарантированно являются действительными символами вообще, и это, как правило, ошибка, если вы видите отдельное char
или wchar
. Несколько chars
или wchars
часто должны объединяться, чтобы составить один символ. Таким образом, вы не можете иметь дело с chars
или wchars
по отдельности. Вот почему, если вы перебираете строку любого вида с foreach, вы должны всегда указывать ее тип как dchar
.
foreach(dchar c; str)
...
Если бы вы не указали dchar
, то это был бы любой тип символа str
, который неизменно вызывал бы ошибки, если бы str
не был массивом dchar
, потому что вы бы в итоге с кодовыми единицами (куски символов) вместо кодовых точек (целые символы). Только dchars
может рассматриваться индивидуально.
Из-за всего этого все строковые типы и символьные массивы считаются диапазонами dchar
независимо от того, каковы их фактические типы элементов. Таким образом, когда вы вызываете popFront
для строки, она может всплыть намного больше, чем просто один char
или wchar
. И если вы вызываете front
, может потребоваться декодировать несколько chars
или wchars
, чтобы вернуть dchar
, который является первым символом в строке. Это означает, что вы не можете рассматривать массивы char
или wchar
как произвольный доступ. 4-й символ может быть 4-м элементом или 12-м. И независимо от того, с какого индекса он начинается, он может быть длиной в несколько единиц кода, поэтому вы не можете просто получить случайный индекс в массиве char
или wchar
и ожидать, что он будет действительным. Таким образом, массивы char
и wchar
являются , а не диапазонами произвольного доступа. Они также не выходные диапазоны.
Подумай об этом. Давайте возьмем символ '\U00010143'
(?
), например. Длина кодового блока 4 для UTF-8 и 2 для UTF-16. Вы не можете просто заполнить любой случайный массив char
или wchar
этим. Если это массив char
, а его длина не кратна 4, то последний (?
) не подходит. Если это массив wchar
, а его длина не кратна 2, то у него будет та же проблема. Таким образом, на самом деле не работает использование функции типа fill
в массиве char
или wchar
.
Теперь с массивом dchar
все будет работать нормально. Поскольку кодовая единица UTF-32 гарантированно является кодовой точкой, каждый символ в массиве dchar
является одним элементом, и он может быть как диапазоном произвольного доступа, так и диапазоном вывода. Итак, если вы хотите использовать функцию типа fill
с символьными массивами, вам нужно использовать массив dchar
. Вы можете использовать std.conv.to
, чтобы преобразовать его в тип массива символов, который вы хотите после этого, но вы не можете заполнить массив char
или wchar
напрямую.
Массивы char
и wchar
прекрасно работают с алгоритмами, которым не нужны выходные диапазоны или диапазоны произвольного доступа, но они не работают с ними. Для них вам нужны массивы dchar
.