Work with Arrays and Spans

Separate owned vectors from borrowed contiguous views before translating array operations.

BeginnerCore.BaseBuilt and run

Goal and component

Own a sequence, take a checked subrange, mutate through the view, and copy overlapping elements safely. All types in this tutorial belong to Core.Base.

Own with vector, borrow with Span

#include <System/Array.hpp>
#include <System/Span.hpp>

#include <vector>

std::vector<int> values{1, 2, 3, 4, 5};
System::Span<int> all(values);
auto middle = all.Slice(1, 3);
middle.Fill(9);

// values is now {1, 9, 9, 9, 5}

The vector owns. The span stores only data() and an element length. Its indexing and slicing are checked, but it cannot keep the vector alive.

Copy overlapping ranges

System::Span<int> source(values.data(), 4);
System::Span<int> destination(values.data() + 1, 4);
source.CopyTo(destination);

// CopyTo chooses an overlap-safe direction.

Do not replace this with memcpy. Overlap requires memmove-like direction, and non-trivial elements require assignment rather than object-representation copying.

Use Array algorithms on owned storage

System::Array::Sort(values);
const auto index = System::Array::IndexOf(values, 9);
System::Array::Reverse(values, 0, 3);

System::Array is a static algorithm class, not a base object. Its vector overloads validate signed ranges. Floating default sort uses the project’s explicit NaN-first policy.

Know what invalidates the view

auto view = System::Span<int>(values);
values.push_back(6); // may reallocate

// Do not use view after a potentially relocating operation.

Reserve is not a permanent lifetime contract: any later operation that exceeds capacity can relocate. Destruction always invalidates. Erase/insert can change which elements an offset describes even when the buffer does not move.

Read-only means through this alias

ReadOnlySpan<T> prevents mutation through the view. Another alias can still mutate the same storage. For a retained immutable value, own a const value or enforce immutability at the owner rather than relying on one read-only borrow.

Do not use current Memory as an async owner

Memory<T> and ReadOnlyMemory<T> borrow a vector in this implementation. Pin() returns its current native pointer but does not retain or immobilize the vector. Cross an async boundary with an explicit owner plus offsets, not a borrowed view alone.

Verification checklist

  • Empty, exact-end, negative, and oversized slices.
  • Overlapping copy in both directions with non-trivial elements.
  • Owner destruction and vector reallocation.
  • Raw-pointer boundaries with explicit capacity proof.
  • Multidimensional index multiplication overflow if using flattened storage.