Является статическим массивом прямого диапазона?

Это работает:

int[] a = [ 1, 2, 3, 4 ];
fill(a, 5);

но это не так:

int[4] a = [ 1, 2, 3, 4 ];
fill(a, 5);

и я получаю эту ошибку:

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

вместо этого я должен сделать это, чтобы он работал со статическими массивами:

int[4] a = [ 1, 2, 3, 4 ];
fill(a[], 5);

Может кто-нибудь объяснить это поведение?

Ответ 1

Нет. 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 является true. Таким образом, он работает. И поскольку срез указывает на те же элементы, а fill мутирует элементы, а не массив, элементы в статическом массиве мутируются с помощью fill.

Будьте осторожны, однако, о передаче срезов статических массивов в функции. Пока существует статический массив, это прекрасно. Но как только статический массив покинет область видимости, любой ее фрагмент окажется недействительным. Итак, что-то вроде

int[] foo()
{
    int[5] a = [1, 2, 3, 4, 5]
    return find(a[], 3);
}

будет очень плохо. Ссылка на a выводит foo - а именно срез его последних 3 элементов.

Итак, если вы передаете срез статического массива функции, вы должны быть уверены, что ссылки на этот массив не исчезают. fill, однако, должно быть хорошо.

Ответ 2

isForwardRange проверяет наличие свойств front, empty и popfront() function

проблема в том, что popfront() нужно будет сжать массив, так как вы (знаете), что не можете изменять размер статического массива, но можно изменить размер среза статического массива (по существу, обычного динамического массива) (это конечно, не влияет на статический массив)

чтобы прояснить a.popfront(), нужно было бы преобразовать a из int[4] в int[3], но это невозможно