Почему std.algorithm.fill не принимает массивы символов? - PullRequest
5 голосов
/ 19 июня 2011

Если я пытаюсь использовать std.algorithm.fill (Range1, Range2) (Range1 range, Range2 наполнитель), я получаю сообщение об ошибке, что не найдено ни одного совпадения шаблона.Похоже, что компилятор пытается сопоставить с заливкой (Range, Value), а не с другим.

auto test = new char[256];
fill(test, "abc".dup);

Разве невозможно заполнить массив символов с помощью fill?

ошибка

test.d (13): Ошибка: шаблон std.algorithm.fill (Range, Value) if (isForwardRange! (Range) && is (typeof (range.front = filler)))не соответствует ни одному объявлению шаблона функции

test.d (13): Ошибка: шаблон std.algorithm.fill (Range, Value), если (isForwardRange! (Range) && is (typeof (range.front = filler)))) не может вывести функцию emplate из типов аргументов! () (char [], char [])

Ответы [ 2 ]

8 голосов
/ 19 июня 2011

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.

2 голосов
/ 19 июня 2011

Потому что typeof (test.front) == dchar, а не char

Это может быть ошибка, но это потому, что typeof(test.front) это dchar, а не char, так как она интерпретируется как строка UTF-8 и дает вам первый символ Unicode, а не первый char .

Но почему это так интерпретируется?

Один из ваших import, вероятно, либо прямо, либо косвенно импортировал такой модуль, как std.array (или что-то в этом роде), чья функция front() возвращает dchar для char[]. Попытайтесь выяснить, какой это, и вместо того, чтобы использовать это, вместо этого выполните import std.iterator; тот возвращает char вместо dchar.

...