№ isForwardRange
- false
для статических массивов, поскольку они недопустимы для дальности вперед. Они должны иметь действительные front
, empty
и popFront
.
Диапазон должен быть мутированным по мере его повторения. popFront
удаляет первый элемент из диапазона, уменьшая длину диапазона на единицу. статические массивы не могут быть мутированы. Их элементов может быть, но их не может быть.
int[5] a;
a.length = 4;
является незаконным. Таким образом, popFront
не может работать со статическими массивами, поэтому статические массивы не могут быть диапазонами.
front
, empty
и popFront
объявлены для массивов в std.array и front
и empty
будет работать со статическими массивами, так как они явно принимают динамические массивы (не диапазоны), и статические массивы могут быть неявно преобразованы в динамические массивы когда функция принимает динамический массив (берется срез статического массива). Однако popFront
не будет работать, поскольку для динамического массива требуется ref
. И, как я указал, popFront
не может быть выполнен для работы со статическими массивами независимо от реализации popFront
, поскольку вы не можете мутировать статический массив, как это требуется для диапазона.
Теперь, как для fill
, он принимает дальний диапазон, а не массив. Таким образом, IFTI (имплицирование неявных функций) будет пытаться использовать с ним тип статического массива (а не тип динамического массива). А так как isForwardRange
является false
для статического массива, fill
не может скомпилироваться со статическим массивом. Однако, когда вы разрезаете статический массив, вы затем передаете динамический массив, для которого isForwardRange
istrue
. Таким образом, он работает.И поскольку срез указывает на те же элементы и fill
мутирует элементы, а не массив, элементы в статическом массиве мутируются на fill
.
Будьте осторожны, однако, передавая кусочки статических массивов в функции. Пока существует статический массив, все в порядке. Но как только статический массив покинет область видимости, любой ее фрагмент окажется недействительным. Итак, что-то вроде
int[] foo()
{
int[5] a = [1, 2, 3, 4, 5]
return find(a[], 3);
}
было бы очень плохо. Ссылка на a
ускользает от foo
- а именно среза его последних 3 элементов.
Итак, если вы передаете срез статического массива функции, вы должны быть уверены, что ссылки на этот массив не исчезают. fill
, однако, должно быть хорошо.
Правильно ли я говорю, что вам нужно обрезать «Array» и «SList»? Похоже, что это недостаток дизайна. –
Это не дизайн дефекта ИМХО. Это скорее случай, когда динамические массивы представляют собой странный частный случай диапазонов. Но так как в настоящее время это самый распространенный случай, это то, к чему мы привыкли. Контейнеру нужно было бы неявно преобразовать его в свой тип среза для IFTI, чтобы он не нуждался в явном разрезе при передаче функции, и что было бы намного сложнее передать контейнеры в шаблонные функции. И я не уверен, что было бы хорошей идеей, чтобы все разрезанные типы были автоматически разрезаны с помощью IFTI в целом - даже при работе с диапазонами. –
Вы можете думать об этом так. Контейнеры, включая статические массивы, должны быть нарезаны, чтобы получить диапазон над ними. Таким образом, если вы хотите, чтобы диапазон по ним по какой-либо причине - включая переход к функции на основе диапазона, - вы должны явно нарезать их. Но динамические массивы - это уже _ диапазоны, а не контейнеры, поэтому нарезка не нужна. –