A move-only, fixed-capacity array with runtime-determined length and RAII-based ownership.
More...
|
| | runtime_arr (const std::uint64_t size, uninitialized_t) |
| | Constructs an uninitialized array of POD-like elements.
|
| | runtime_arr (std::initializer_list< T > init) |
| | Constructs a fixed-size runtime array from an initializer list.
|
| | runtime_arr (std::uint64_t size) |
| | Constructs a zero-initialized array using the default allocation strategy.
|
| | runtime_arr (std::initializer_list< T > init, const Alloc &alloc) |
| | Constructs a fixed-size runtime array from an initializer list using a custom allocator.
|
| | runtime_arr (std::uint64_t size, const Alloc &alloc) |
| | Constructs a runtime array using a movable allocator instance.
|
| | runtime_arr (std::vector< T > &&vec) |
| | Constructs a runtime_arr<T> by moving from a std::vector<T> (only when Alloc is typed::monostate).
|
template<class VecAlloc>
requires (!typed::monostate_t<Alloc>) |
| | runtime_arr (std::vector< T, VecAlloc > &&vec, const Alloc &alloc) |
| | Constructs a runtime array by moving elements from a std::vector using a custom allocator.
|
| | runtime_arr (std::vector< T, Alloc > &&vec) |
| | Constructs a runtime array by moving elements from a std::vector using its own allocator.
|
template<typename ForwardIt>
requires (jh::concepts::forward_iterator<ForwardIt> && (typed::monostate_t<Alloc> || std::default_initializable<Alloc>) ) |
| | runtime_arr (ForwardIt first, ForwardIt last) |
| | Constructs a runtime_arr<T> from any valid forward iterator range.
|
template<typename ForwardIt>
requires (!typed::monostate_t<Alloc> && jh::concepts::forward_iterator<ForwardIt> && requires (ForwardIt f, ForwardIt l) { std::vector<T>(f, l); }) |
| | runtime_arr (ForwardIt first, ForwardIt last, const Alloc &alloc) |
| | Constructs a runtime array from a forward iterator range using a custom allocator.
|
|
iterator | begin () noexcept |
| | Returns iterator to the beginning.
|
|
const_iterator | begin () const noexcept |
| | Returns const iterator to the beginning.
|
|
iterator | end () noexcept |
| | Returns iterator to the end (past-the-last element).
|
|
const_iterator | end () const noexcept |
| | Returns const iterator to the end (past-the-last element).
|
|
const_iterator | cbegin () const noexcept |
| | Returns const iterator to the beginning.
|
|
const_iterator | cend () const noexcept |
| | Returns const iterator to the end (past-the-last element).
|
| reference | operator[] (std::uint64_t index) noexcept |
| | Unchecked element access.
|
| const_reference | operator[] (std::uint64_t index) const noexcept |
| | Unchecked const element access.
|
| reference | at (std::uint64_t index) |
| | Bounds-checked element access.
|
| const_reference | at (std::uint64_t index) const |
| | Const bounds-checked element access.
|
| template<typename... Args> |
| void | set (std::uint64_t i, Args &&... args) |
| | Sets the value at given index using constructor arguments.
|
| template<typename U = T> |
| void | reset_all () noexcept |
| | Resets all elements to their default-initialized state.
|
| size_type | size () const noexcept |
| | Returns the number of elements in the array.
|
| bool | empty () const noexcept |
| | Checks whether the array is empty.
|
| pointer | data () noexcept |
| | Provides raw pointer access to the underlying storage.
|
| const_pointer | data () const noexcept |
| | Provides const raw pointer access to the underlying storage.
|
| | runtime_arr (runtime_arr &&other) noexcept |
| | Constructs a new runtime_arr by taking ownership of another instance's data.
|
| runtime_arr & | operator= (runtime_arr &&other) noexcept |
| | Replaces the contents of this runtime_arr with those of another, transferring ownership.
|
| | operator std::vector< T > () && |
| | Converts the array into a std::vector<T> by moving its contents.
|
| | runtime_arr (const runtime_arr &)=delete |
| | Copy constructor is explicitly deleted.
|
| runtime_arr & | operator= (const runtime_arr &)=delete |
| | Copy assignment operator is explicitly deleted.
|
|
std::span< value_type > | as_span () noexcept |
|
std::span< const value_type > | as_span () const noexcept |
template<typename T, typename Alloc = typed::monostate>
requires detail::valid_rt_arr_allocator<T, Alloc>
class jh::runtime_arr< T, Alloc >
A move-only, fixed-capacity array with runtime-determined length and RAII-based ownership.
- Template Parameters
-
| T | Element type. |
| Alloc | Allocator type — defaults to typed::monostate (uses new[] / delete[]). |
Overview
Short for "runtime-sized array", this class models a heap-allocated, non-resizable container designed as a safe and expressive replacement for manual heap buffers (new T[n]).
Unlike std::vector, it forbids resizing, shrinking, or growth semantics. It focuses on semantic clarity rather than raw performance — making buffer lifetime and capacity constraints explicit.
Core Features
-
Move-only: eliminates accidental copies and aliasing.
-
RAII-managed heap buffer (via
unique_ptr<T[], deleter>).
-
Optional zero-initialized or uninitialized construction.
-
STL/ranges compatible (
view_interface inheritance).
-
reset_all() for fast POD reset using memset.
-
Allocator parameterization for custom memory control.
-
as_span() helper for safe interop with std::span<T>.
Default Allocation Model
-
If
Alloc = typed::monostate (default):
-
Memory is allocated via
new[] and released via delete[].
-
No external allocator is required.
-
If
Alloc provides allocate(n) / deallocate(ptr, n):
-
Runtime allocation will use the provided allocator instance.
When to Use
-
As a fixed-capacity buffer with dynamic runtime length.
-
When
std::vector's resizing semantics are undesired.
-
As a safer RAII alternative to
T* arr = new T[n].
When Not to Use
-
If dynamic resizing, push/pop semantics, or polymorphic behavior is required.
-
If compile-time fixed capacity (
std::array) suffices.
Interop Notes
-
Contiguous and
std::span-compatible.
-
Supports range-for iteration, STL algorithms, and
std::ranges::views.
-
runtime_arr<bool> provides bit-packed specialization (see below).
- Note
-
Use
reset_all() instead of clear().
-
Use
runtime_arr<T>::uninitialized to skip default construction (POD only).
-
Copy operations are deleted; moves are noexcept.
template<typename T, typename Alloc = typed::monostate>
Constructs an uninitialized array of POD-like elements.
- Parameters
-
| size | The number of elements to allocate. |
-
Enabled only when
jh::pod_like<T> and Alloc is typed::monostate.
-
Uses
operator new[] to allocate raw storage — the memory is completely uninitialized (no zero-fill, no constructor calls).
-
For POD-like types, such uninitialized allocation is semantically safe: their lifetime is bound directly to the allocated storage, and no constructor/destructor side effects are required.
-
Intended for performance-critical contexts such as bulk I/O buffers, custom serialization, or explicit zero-fill via
std::memset.
-
In practice, this behaves similarly to
std::vector::reserve() — capacity is guaranteed, but elements are not value-initialized.
-
Unlike
std::vector, however, runtime_arr does not incur large penalties when default-initializing POD types: its "initialized" and "uninitialized" paths compile to nearly identical code for trivial objects (difference <1%).
Performance note
For POD and trivially constructible types, both initialized and uninitialized variants of runtime_arr achieve equivalent performance. The uninitialized form primarily exists to express intent — much like calling std::vector::reserve() — signaling intent that the elements will be explicitly initialized later, and thus avoiding redundant zero-fills or value-initialization writes that compilers may otherwise emit. For POD and trivially constructible types, however, both forms typically compile to identical machine code, since their constructors are effectively no-ops.
Note: The content of the allocated memory is indeterminate until written to. Accessing any element before explicit initialization results in undefined behavior.
template<typename T, typename Alloc = typed::monostate>
| jh::runtime_arr< T, Alloc >::runtime_arr |
( |
const runtime_arr< T, Alloc > & | | ) |
|
|
delete |
Copy constructor is explicitly deleted.
Copying a runtime_arr is intentionally disallowed, as the class models a fixed-size, region-bound buffer — conceptually similar to a safe version of a VLA (Variable Length Array).
Each runtime_arr instance owns a unique contiguous memory block via std::unique_ptr. Allowing copy semantics would imply duplicating or aliasing this region, violating its design goal of unique, region-local ownership.
To share or pass an existing array, use references: runtime_arr& or std::reference_wrapper<runtime_arr>. This preserves ownership while allowing safe, non-copy access across function boundaries.
template<typename T, typename Alloc = typed::monostate>
Converts the array into a std::vector<T> by moving its contents.
This conversion performs a one-way ownership transfer from runtime_arr<T> to std::vector<T>, consuming the source in the process. After the conversion, the original runtime_arr becomes an empty, valid but unspecified object (size() == 0, data() == nullptr).
Behavior
-
POD-like types (
jh::pod_like<T>): Performs a raw std::memcpy for maximal performance. The operation is equivalent to copying a contiguous byte buffer.
-
Non-POD types: Uses
std::make_move_iterator to move-construct each element into the target vector, ensuring proper object semantics.
Symmetry
This operator complements the constructor runtime_arr(std::vector<T>&&), enabling seamless two-way transfer between std::vector<T> and runtime_arr<T> with full move semantics. Both conversions leave the source container in a valid but empty state, ensuring safe RAII destruction.
- Note
- This operator is only available on rvalues (
runtime_arr<T>&&), preventing accidental copies.
- See also
- runtime_arr(std::vector<T>&&)