This works:
int[] a = [ 1, 2, 3, 4 ];
fill(a, 5);
but this doesn't:
int[4] a = [ 1, 2, 3, 4 ];
fill(a, 5);
and I get this error:
Error: template std.algorithm.fill(Range,Value) if (isForwardRange!(Range) && is(typeof(range.front = filler))) does not match any function template declaration
instead, I have to do this in order for it to work with static arrays:
int[4] a = [ 1, 2, 3, 4 ];
fill(a[], 5);
could any one explain this behavior please?
Static arrays have their size or length determined when the array is created and/or allocated. For this reason, they may also be referred to as fixed-length arrays or fixed arrays. Array values may be specified when the array is defined, or the array size may be defined without specifying array contents.
C++ Arrays DiscussionA statically allocated array variable is a constant pointer that points to a fixed size array in automatic storage (i.e. the call stack), the values of the elements of a static array can be changed but a new array cannot be assigned to a static array variable.
Statically declared arrays are allocated memory at compile time and their size is fixed, i.e., cannot be changed later. They can be initialized in a manner similar to Java. For example two int arrays are declared, one initialized, one not. Static multi-dimensional arrays are declared with multiple dimensions.
Disadvantages of Static ArrayIn case more static data space is declared than needed, there is waste of space. In case less static space is declared than needed, then it becomes impossible to expand this fixed size during run time.
No. isForwardRange
is false
for static arrays, because they're not valid forward ranges. They must have a valid front
, empty
, and popFront
.
A range must be mutated as it's iterated over. popFront
removes the first element from the range, reducing the length of the range by one. static arrays cannot be mutated. Their elements can be, but they can't be.
int[5] a;
a.length = 4;
is illegal. So, popFront
cannot work with static arrays and therefore static arrays cannot be ranges.
front
, empty
, and popFront
are declared for arrays in std.array, and front
and empty
will work with static arrays, because they explicitly take dynamic arrays (not ranges), and static arrays can be implicitly converted to dynamic arrays when a function takes a dynamic array (a slice of the static array is taken). However, popFront
won't work, because it requires a ref
of a dynamic array. And as, I pointed out, popFront
can't be made to work with static arrays regardless of popFront
's implementation, because you can't mutate a static array as would be required for a range.
Now as for fill
, it takes a forward range, not an array. So, IFTI (implicit function template instantiation) will try and use the static array type (not the dynamic array type) with it. And since isForwardRange
is false
for a static array, fill
fails to compile with a static array. However, when you slice the static array, you're then passing a dynamic array, for which isForwardRange
is true
. So, it works. And because, the slice points to the same elements, and fill
mutates the elements and not the array, the elements in the static array are mutated by fill
.
Be wary, however, of passing slices of static arrays to functions. As long as the static array exists, it's fine. But once the static array leaves scope, any slice of it is then invalid. So, doing something like
int[] foo()
{
int[5] a = [1, 2, 3, 4, 5]
return find(a[], 3);
}
would be very bad. A reference to a
is escaping foo
- namely a slice of its last 3 elements.
So, if you are passing a slice of a static array to a function, you need to be sure that no references to that array escape. fill
, however, should be fine.
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