Arrays¶
A fixed array is one object containing a compile-time number of elements of one element type. The count is part of the array's type.
Array types¶
An array type places the element count before the element type:
[4]I32 and [5]I32 are different types. Nested arrays associate through the
written element type: [3][2]I32 contains three elements, each of type
[2]I32.
The count must resolve to a nonnegative compile-time integer. A zero-length array is valid and contains no element objects.
Default construction¶
Omitting an initializer default-constructs every element in increasing index order:
Default construction is available only when the element type has an applicable no-argument constructor. A zero-length array performs no element construction.
Positional initialization¶
:[...] supplies one initializer for each element:
The number of entries must exactly equal the array count. Each entry initializes the corresponding element using that element type's constructor selection. Too few or too many entries are compilation errors.
Positional construction works with user-defined element types:
The array expression form invokes the same constructor surface:
See Variables for the distinction among no-argument, :=,
:(...), and :[...] initialization.
Copy and move construction¶
Copy construction copies corresponding elements. Move construction moves corresponding elements from a temporary-qualified source:
The operation is available when the element type supports the required constructor.
Indexing¶
array[index] selects an element and preserves access qualification:
A mutable array provides mutable element access; a constant array does not.
The index must use a supported integer form. Access is valid only for indices
from zero through N - 1; a zero-length array has no valid element index.
array[& index] produces a pointer to an element instead of a reference-like
element access:
The pointer remains tied to the array object's lifetime and valid bounds.
Arrays do not require an implicit decay to a pointer; use [& index],
BEGIN(), or another explicit pointer-producing operation.
Iteration¶
BEGIN() returns an array pointer to the first element and END() returns the
one-past endpoint:
VAR cursor MUT=>>I32 := initialized.BEGIN();
VAR end MUT=>>I32 := initialized.END();
LOOP WHILE (cursor != end) DO
{
consume(@value cursor->);
cursor++;
}
For [N]T, advancing BEGIN() by N elements reaches END(). For [0]T,
BEGIN() equals END() and neither may be dereferenced.
Array iteration also integrates with LOOP:
ITEM binds writable element access for a mutable array; VALUE creates the
loop's projected value according to the iterator projection rules.
Assignment, swap, and comparison¶
Array assignment applies assignment to corresponding elements. <-> swaps
corresponding elements. These operations require equal array types and the
corresponding element operation:
Equality compares corresponding elements. Three-way and relative comparison use the array's generated comparison path when the element type supplies the required comparisons. Array length does not need runtime comparison because it is already fixed by the common type.
Destruction and lifetime¶
An array owns all of its elements. Destroying the array destroys every live nontrivial element in reverse construction order. References and pointers to elements do not extend the array lifetime.
Raw storage for an array is not an array object until PLACE or another
constructor begins its lifetime. See Object Storage and Lifetime
for explicit lifetime operations and Pointers for array-pointer
arithmetic and validity rules.
Bounds policy¶
Element access requires an index below the array length. Taking an element
address with [& index] permits the one-past index equal to the length; that
pointer cannot be dereferenced. CHECK_BOUNDS controls runtime checks for
these operations. Disabling it preserves the bounds requirement. Constant
evaluation checks bounds. See Compilation Policies.