MT Core (C++)
Core library for replacing C++ standard in project usage
Loading...
Searching...
No Matches
mtcore::ArrayList< T > Struct Template Reference

Array list is a growable, dynamic array with elements inside Elements are stored in an array, and are copied when resizing needs to happen Accessing elements is \(O(1)\) Adding elements is worst case \(O(N)\) Removing elements while preserving order is \(O(N)\) Removing elements while not preserving order is \(O(1)\). More...

#include <array_list.hpp>

Inheritance diagram for mtcore::ArrayList< T >:

Public Types

using Elem = T
 

Public Member Functions

decltype(auto) ptr_iter () noexcept
 Gets iterator over pointers to elements.
 
decltype(auto) ptr_iter () const noexcept
 Gets iterator over const pointers to elements.
 
decltype(auto) iter () const noexcept
 Gets iterator over values.
 
Result< void, AllocationErrorinit (Allocator &alloc, size_t initCapacity=10) noexcept
 Initializes an empty ArrayList with an initial capacity.
 
Result< void, AllocationErrorinit (Allocator &alloc, std::initializer_list< T > init, size_t capacity=0) noexcept
 Initializes an array list with specified elements.
 
void deinit (Allocator &alloc) noexcept
 Cleans up any memory held by array list.
 
Result< void, AllocationErrorpush (Allocator &alloc, const Slice< std::add_const_t< T > > &elems) noexcept
 Pushes a list of items onto an array list.
 
Result< void, AllocationErrorpush (Allocator &alloc, const Slice< std::remove_const_t< T > > &elems) noexcept
 Pushes a list of items onto an array list.
 
Result< void, AllocationErrorpush (Allocator &alloc, const T &elem) noexcept
 Pushes an item onto an array list.
 
size_t size () const noexcept
 Gets the size of an array list.
 
size_t capacity () const noexcept
 Array list capacity.
 
Result< void, AllocationErrorreserve (Allocator &alloc, const size_t newSize) noexcept
 Will grow the capacity to be at least newSize large.
 
Result< void, AllocationErrorshrink_to_fit (Allocator &alloc) noexcept
 Will shrink the capacity to match the current size.
 
Result< void, CollectionAddNoAllocationErrorpush (const Slice< std::remove_const_t< T > > &elems) noexcept
 Pushes an item onto the end of the ArrayList Will fail if there is not enough room.
 
Result< void, CollectionAddNoAllocationErrorpush (const Slice< std::add_const_t< T > > &elems) noexcept
 Pushes an item onto the end of the ArrayList Will fail if there is not enough room.
 
Result< void, CollectionAddNoAllocationErrorpush (const T &elem) noexcept
 Pushes an item onto the end of the ArrayList Will fail if there is not enough room.
 
Result< void, AllocationErrorunshift (const T &elem) noexcept
 Adds an element to the front, and shifts all other elements down by 1 If there is not enough room, will Result in a failure.
 
Result< void, AllocationErrorunshift (Allocator &alloc, const T &elem) noexcept
 Adds an element to the front, and shifts all other elements down by 1 If there is not enough room, will try to allocate more room.
 
Optional< T > shift () noexcept
 Removes the first element and shifts all remaining elements down.
 
Optional< T > pop () noexcept
 Pops the last element and returns it Will return an error if there is no element.
 
T & at (size_t index) noexcept
 Get element at an index.
 
const T & at (size_t index) const noexcept
 Get element at an index.
 
T & operator[] (size_t index) noexcept
 Get element at an index.
 
const T & operator[] (size_t index) const noexcept
 Get element at an index.
 
swap_remove (size_t index) noexcept
 Removes the element at an index (must be present) Does NOT preserve ordering Will swap the removed element with the last element and then pop Completes in \(O(1)\).
 
shift_remove (size_t index) noexcept
 Removes the element at an index (must be present) Does preserve ordering Will shift all remaining elements over by one Completes in \(O(N)\).
 
Slice< T > slice ()
 Gets a slice over the underlying elements.
 
Slice< std::add_const_t< T > > slice () const
 Gets a slice over the underlying elements.
 

Detailed Description

template<typename T>
struct mtcore::ArrayList< T >

Array list is a growable, dynamic array with elements inside Elements are stored in an array, and are copied when resizing needs to happen Accessing elements is \(O(1)\) Adding elements is worst case \(O(N)\) Removing elements while preserving order is \(O(N)\) Removing elements while not preserving order is \(O(1)\).

Template Parameters
TElements to store

Definition at line 46 of file array_list.hpp.

Member Typedef Documentation

◆ Elem

template<typename T>
using mtcore::ArrayList< T >::Elem = T

Definition at line 52 of file array_list.hpp.

Member Function Documentation

◆ at() [1/2]

template<typename T>
const T & mtcore::ArrayList< T >::at ( size_t index) const
inlinenodiscardnoexcept

Get element at an index.

Parameters
indexElement index to get
Returns
Element reference

Definition at line 387 of file array_list.hpp.

387 {
388 ensure(elements.head, "NOT INITIALIZED");
389 return elements[index];
390 }
#define ensure(check,...)
Ensures that a check holds true, aborts the program if not true Will print error if the condition is ...
Array list is a growable, dynamic array with elements inside Elements are stored in an array,...

◆ at() [2/2]

template<typename T>
T & mtcore::ArrayList< T >::at ( size_t index)
inlinenodiscardnoexcept

Get element at an index.

Parameters
indexElement index to get
Returns
Element reference

Definition at line 377 of file array_list.hpp.

377 {
378 ensure(elements.head, "NOT INITIALIZED");
379 return elements[index];
380 }

◆ capacity()

template<typename T>
size_t mtcore::ArrayList< T >::capacity ( ) const
inlinenodiscardnoexcept

Array list capacity.

Returns
capacity of array list

Definition at line 196 of file array_list.hpp.

196 {
197 ensure(count <= elements.len, "COUNT EXCEEDS SLICE SIZE!");
198 return elements.len;
199 }
Here is the caller graph for this function:

◆ deinit()

template<typename T>
void mtcore::ArrayList< T >::deinit ( Allocator & alloc)
inlinenoexcept

Cleans up any memory held by array list.

Parameters
allocAllocator to use for cleanup

Definition at line 121 of file array_list.hpp.

121 {
122 if (elements.head != nullptr) {
123 alloc.destroy_many(elements);
124 elements.head = nullptr;
125 }
126 elements.len = 0;
127 }

◆ init() [1/2]

template<typename T>
Result< void, AllocationError > mtcore::ArrayList< T >::init ( Allocator & alloc,
size_t initCapacity = 10 )
inlinenoexcept

Initializes an empty ArrayList with an initial capacity.

Parameters
allocAllocator to use for initial allocation
initCapacity(Optional) Initial capacity to have (defaults to 10)
Returns
success or failure

Definition at line 76 of file array_list.hpp.

76 {
77 ensure(elements.head == nullptr && elements.size() == 0, "ALREADY INITIALIZED!");
79 auto allocRes = alloc.create_many<T>(initCapacity);
80 if (allocRes.is_error()) {
81 return allocRes.error();
82 }
83
84 elements = *allocRes;
85 return success();
86 }
Success< void > success()
Creates a successful void Result object.
Definition result.hpp:398
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init() [2/2]

template<typename T>
Result< void, AllocationError > mtcore::ArrayList< T >::init ( Allocator & alloc,
std::initializer_list< T > init,
size_t capacity = 0 )
inlinenoexcept

Initializes an array list with specified elements.

Parameters
allocAllocator to use for initial allocation
initInitial value list
capacity(Optional) initial capacity (if bigger than the initial value list)
Returns
success or failure

Definition at line 96 of file array_list.hpp.

96 {
97 ensure(elements.head == nullptr && elements.size() == 0, "ALREADY INITIALIZED!");
98 if (capacity < init.size()) {
99 capacity = init.size();
100 }
101 capacity = capacity ? capacity : 10;
102 auto allocRes = alloc.create_many<T>(init.size());
103 if (allocRes.is_error()) {
104 return allocRes.error();
105 }
106
107 elements = *allocRes;
108 size_t index = 0;
109 for (const auto &elem: init) {
110 elements[index++] = elem;
111 }
112 count = index;
113
114 return success();
115 }
Result< void, AllocationError > init(Allocator &alloc, size_t initCapacity=10) noexcept
Initializes an empty ArrayList with an initial capacity.
size_t capacity() const noexcept
Array list capacity.
Here is the call graph for this function:

◆ iter()

template<typename T>
decltype(auto) mtcore::ArrayList< T >::iter ( ) const
inlinenodiscardnoexcept

Gets iterator over values.

Returns
Iterator

Definition at line 68 of file array_list.hpp.

68{ return iter::val(*this); }
ValIter< T > val(const T &r)
Generic value iterator that uses the operator[] and incrementing indexes to iterate over a collection...
Definition iter.hpp:114
Here is the call graph for this function:

◆ operator[]() [1/2]

template<typename T>
const T & mtcore::ArrayList< T >::operator[] ( size_t index) const
inlinenoexcept

Get element at an index.

Parameters
indexElement index to get
Returns
Element reference

Definition at line 407 of file array_list.hpp.

407 {
408 ensure(elements.head, "NOT INITIALIZED");
409 return elements[index];
410 }

◆ operator[]() [2/2]

template<typename T>
T & mtcore::ArrayList< T >::operator[] ( size_t index)
inlinenoexcept

Get element at an index.

Parameters
indexElement index to get
Returns
Element reference

Definition at line 397 of file array_list.hpp.

397 {
398 ensure(elements.head, "NOT INITIALIZED");
399 return elements[index];
400 }

◆ pop()

template<typename T>
Optional< T > mtcore::ArrayList< T >::pop ( )
inlinenoexcept

Pops the last element and returns it Will return an error if there is no element.

Returns
The element that was removed, or the error EMPTY

Definition at line 363 of file array_list.hpp.

363 {
364 ensure(elements.head, "NOT INITIALIZED");
365 if (count == 0) {
366 return nullopt;
367 }
368 --count;
369 return elements[count];
370 }
Here is the caller graph for this function:

◆ ptr_iter() [1/2]

template<typename T>
decltype(auto) mtcore::ArrayList< T >::ptr_iter ( ) const
inlinenodiscardnoexcept

Gets iterator over const pointers to elements.

Returns
Iterator

Definition at line 63 of file array_list.hpp.

63{ return iter::const_ptr(*this); }
ConstPtrIter< T > const_ptr(const T &r)
Generic constant pointer iterator that uses the operator[] and incrementing indexes to iterate over a...
Definition iter.hpp:128
Here is the call graph for this function:

◆ ptr_iter() [2/2]

template<typename T>
decltype(auto) mtcore::ArrayList< T >::ptr_iter ( )
inlinenodiscardnoexcept

Gets iterator over pointers to elements.

Returns
Iterator

Definition at line 58 of file array_list.hpp.

58{ return iter::ptr(*this); }
PtrIter< T > ptr(T &r)
Generic pointer iterator that uses the operator[] and incrementing indexes to iterate over a collecti...
Definition iter.hpp:101
Here is the call graph for this function:

◆ push() [1/6]

template<typename T>
Result< void, AllocationError > mtcore::ArrayList< T >::push ( Allocator & alloc,
const Slice< std::add_const_t< T > > & elems )
inlinenoexcept

Pushes a list of items onto an array list.

If there is no more room, will allocate a new list and do a copy If allocation fails, will return a failure

Parameters
allocAllocator to use for potential allocations
elemsElements to add
Returns
Success or failure (failure happens if ArrayList cannot get more memory)

Definition at line 137 of file array_list.hpp.

137 {
138 ensure(elements.head, "NOT INITIALIZED");
139 if (count + elems.size() >= elements.len) {
140 size_t newSize = elements.len + std::max(((elements.len + 1) / 2), elems.size());
141 if (auto res = reserve(alloc, newSize); res.is_error()) {
142 return res;
143 }
144 }
145
146 ensure(push(elems).is_success(), "SOMEHOW GIVING MORE SPACE DIDN'T WORK");
147 return success();
148 }
Result< void, AllocationError > push(Allocator &alloc, const Slice< std::add_const_t< T > > &elems) noexcept
Pushes a list of items onto an array list.
Result< void, AllocationError > reserve(Allocator &alloc, const size_t newSize) noexcept
Will grow the capacity to be at least newSize large.
size_t size() const noexcept
Gets the size of an array list.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ push() [2/6]

template<typename T>
Result< void, AllocationError > mtcore::ArrayList< T >::push ( Allocator & alloc,
const Slice< std::remove_const_t< T > > & elems )
inlinenoexcept

Pushes a list of items onto an array list.

If there is no more room, will allocate a new list and do a copy If allocation fails, will return a failure

Parameters
allocAllocator to use for potential allocations
elemsElements to add
Returns
Success or failure (failure happens if ArrayList cannot get more memory)

Definition at line 158 of file array_list.hpp.

158 {
159 return push(alloc, elems.to_const());
160 }
Here is the call graph for this function:

◆ push() [3/6]

template<typename T>
Result< void, AllocationError > mtcore::ArrayList< T >::push ( Allocator & alloc,
const T & elem )
inlinenoexcept

Pushes an item onto an array list.

If there is no more room, will allocate a new list and do a copy If allocation fails, will return a failure

Parameters
allocAllocator to use for potential allocations
elemElement to add
Returns
Success or failure (failure happens if ArrayList cannot get more memory)

Definition at line 170 of file array_list.hpp.

170 {
171 ensure(elements.head, "NOT INITIALIZED");
172 if (count >= elements.len) {
173 size_t newSize = elements.len + ((elements.len + 1) / 2);
174 if (auto res = reserve(alloc, newSize); res.is_error()) {
175 return res;
176 }
177 }
178
179 ensure(push(elem).is_success(), "SOMEHOW GIVING MORE SPACE DIDN'T WORK");
180 return success();
181 }
Here is the call graph for this function:

◆ push() [4/6]

template<typename T>
Result< void, CollectionAddNoAllocationError > mtcore::ArrayList< T >::push ( const Slice< std::add_const_t< T > > & elems)
inlinenoexcept

Pushes an item onto the end of the ArrayList Will fail if there is not enough room.

Parameters
elemsElement to add
Returns
success (had room) or failure (no room)

Definition at line 272 of file array_list.hpp.

272 {
273 ensure(elements.head, "NOT INITIALIZED");
274 if (count + elems.size() > elements.len) {
276 }
277
278 for (size_t i = 0; i < elems.size(); ++i) {
279 elements[count++] = elems[i];
280 }
281
282 return success();
283 }
Error< Underlying > error(Underlying err)
Creates an error.
Definition result.hpp:425
Here is the call graph for this function:

◆ push() [5/6]

template<typename T>
Result< void, CollectionAddNoAllocationError > mtcore::ArrayList< T >::push ( const Slice< std::remove_const_t< T > > & elems)
inlinenoexcept

Pushes an item onto the end of the ArrayList Will fail if there is not enough room.

Parameters
elemsElement to add
Returns
success (had room) or failure (no room)

Definition at line 262 of file array_list.hpp.

262 {
263 return push(elems.to_const());
264 }
Here is the call graph for this function:

◆ push() [6/6]

template<typename T>
Result< void, CollectionAddNoAllocationError > mtcore::ArrayList< T >::push ( const T & elem)
inlinenoexcept

Pushes an item onto the end of the ArrayList Will fail if there is not enough room.

Parameters
elemElement to add
Returns
success (had room) or failure (no room)

Definition at line 291 of file array_list.hpp.

291 {
292 ensure(elements.head, "NOT INITIALIZED");
293 if (count >= elements.len) {
295 }
296
297 elements[count++] = elem;
298 return success();
299 }
Here is the call graph for this function:

◆ reserve()

template<typename T>
Result< void, AllocationError > mtcore::ArrayList< T >::reserve ( Allocator & alloc,
const size_t newSize )
inlinenoexcept

Will grow the capacity to be at least newSize large.

Parameters
allocAllocator to use to resize
newSizeNew minimum capacity size
Returns
Result

Definition at line 207 of file array_list.hpp.

207 {
208 ensure(elements.head, "NOT INITIALIZED");
209 ensure(count <= elements.len, "COUNT EXCEEDS SLICE SIZE!");
210 if (newSize <= capacity()) {
211 return success();
212 }
213 ensure(newSize > size(), "FAILED TO GROW");
214 auto newElemAllocRes = alloc.create_many<T>(newSize);
215 if (newElemAllocRes.is_error()) {
216 return newElemAllocRes.error();
217 }
218
220 for (size_t i = 0; i < elements.size(); ++i) {
221 std::swap(newElems[i], elements[i]);
222 }
223 alloc.destroy_many(elements);
224 elements = newElems;
225 return success();
226 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shift()

template<typename T>
Optional< T > mtcore::ArrayList< T >::shift ( )
inlinenoexcept

Removes the first element and shifts all remaining elements down.

Returns
The element that was removed

Definition at line 350 of file array_list.hpp.

350 {
351 ensure(elements.head, "NOT INITIALIZED");
352 if (count == 0) {
353 return nullopt;
354 }
355 return shift_remove(0);
356 }
T shift_remove(size_t index) noexcept
Removes the element at an index (must be present) Does preserve ordering Will shift all remaining ele...
Here is the call graph for this function:

◆ shift_remove()

template<typename T>
T mtcore::ArrayList< T >::shift_remove ( size_t index)
inlinenoexcept

Removes the element at an index (must be present) Does preserve ordering Will shift all remaining elements over by one Completes in \(O(N)\).

Parameters
indexIndex of element to remove. Must be a valid index
Returns
The removed element

Definition at line 441 of file array_list.hpp.

441 {
442 ensure(elements.head, "NOT INITIALIZED");
443 ensure(index < count, "ARRAY OUT OF BOUNDS DETECTED!");
444
445 for (size_t i = index; i + 1 < count; ++i) {
446 std::swap(elements[index], elements[index + 1]);
447 }
448 auto popRes = pop();
449 ensure(popRes, "COULDN'T REMOVE ELMENT FROM NON-EMPTY LIST");
450 return *popRes;
451 }
Optional< T > pop() noexcept
Pops the last element and returns it Will return an error if there is no element.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shrink_to_fit()

template<typename T>
Result< void, AllocationError > mtcore::ArrayList< T >::shrink_to_fit ( Allocator & alloc)
inlinenoexcept

Will shrink the capacity to match the current size.

Parameters
allocAllocator to use to resize
Returns
Result

Definition at line 233 of file array_list.hpp.

233 {
234 ensure(elements.head, "NOT INITIALIZED");
235 ensure(count <= elements.len, "COUNT EXCEEDS SLICE SIZE!");
236 auto newSize = size();
237 if (newSize == capacity()) {
238 return success();
239 }
240
241 ensure(newSize < size(), "FAILED TO SHRINK");
242 auto newElemAllocRes = alloc.create_many<T>(newSize);
243 if (!newElemAllocRes) {
244 return newElemAllocRes;
245 }
246
248 for (size_t i = 0; i < elements.size(); ++i) {
249 std::swap(newElems[i], elements[i]);
250 }
251 alloc.destroy_many(elements);
252 elements = newElems;
253 return success();
254 }
Here is the call graph for this function:

◆ size()

template<typename T>
size_t mtcore::ArrayList< T >::size ( ) const
inlinenodiscardnoexcept

Gets the size of an array list.

Returns
Size of the list

Definition at line 187 of file array_list.hpp.

187 {
188 ensure(count <= elements.len, "COUNT EXCEEDS SLICE SIZE!");
189 return count;
190 }
Here is the caller graph for this function:

◆ slice() [1/2]

template<typename T>
Slice< T > mtcore::ArrayList< T >::slice ( )
inlinenodiscard

Gets a slice over the underlying elements.

Definition at line 456 of file array_list.hpp.

456{ return elements.sub(0, count); }

◆ slice() [2/2]

template<typename T>
Slice< std::add_const_t< T > > mtcore::ArrayList< T >::slice ( ) const
inlinenodiscard

Gets a slice over the underlying elements.

Definition at line 461 of file array_list.hpp.

461{ return elements.sub(0, count).to_const(); }

◆ swap_remove()

template<typename T>
T mtcore::ArrayList< T >::swap_remove ( size_t index)
inlinenoexcept

Removes the element at an index (must be present) Does NOT preserve ordering Will swap the removed element with the last element and then pop Completes in \(O(1)\).

Parameters
indexIndex of element to remove. Must be a valid index
Returns
The removed element

Definition at line 420 of file array_list.hpp.

420 {
421 ensure(elements.head, "NOT INITIALIZED");
422 ensure(index < count, "ARRAY OUT OF BOUNDS DETECTED!");
423 auto end = count - 1;
424 if (index != end) {
425 std::swap(elements[end], elements[index]);
426 }
427
428 auto popRes = pop();
429 ensure(popRes.has_value(), "COULDN'T REMOVE ELMENT FROM NON-EMPTY LIST");
430 return *popRes;
431 }
Here is the call graph for this function:

◆ unshift() [1/2]

template<typename T>
Result< void, AllocationError > mtcore::ArrayList< T >::unshift ( Allocator & alloc,
const T & elem )
inlinenoexcept

Adds an element to the front, and shifts all other elements down by 1 If there is not enough room, will try to allocate more room.

Parameters
allocAllocator to use to grow (if needed)
elemElement to add
Returns
success or failure

Definition at line 330 of file array_list.hpp.

330 {
331 ensure(elements.head, "NOT INITIALIZED");
332 // add the new element to the end
333 if (auto err = push(alloc, elem)) {
334 return err;
335 }
336
337 // then bubble the last element down
338 for (size_t i = 0; i + 1 < count; ++i) {
339 const auto upper = count - 1 - i;
340 const auto lower = count - 2 - i;
341 std::swap(elements[upper], elements[lower]);
342 }
343 return success();
344 }
Here is the call graph for this function:

◆ unshift() [2/2]

template<typename T>
Result< void, AllocationError > mtcore::ArrayList< T >::unshift ( const T & elem)
inlinenoexcept

Adds an element to the front, and shifts all other elements down by 1 If there is not enough room, will Result in a failure.

Parameters
elemElement to add
Returns
success or failure

Definition at line 307 of file array_list.hpp.

307 {
308 ensure(elements.head, "NOT INITIALIZED");
309 // add the new element to the end
310 if (auto err = push(elem)) {
311 return err;
312 }
313
314 // then bubble the last element down
315 for (size_t i = 0; i + 1 < count; ++i) {
316 const auto upper = count - 1 - i;
317 const auto lower = count - 2 - i;
318 std::swap(elements[upper], elements[lower]);
319 }
320 return success();
321 }
Here is the call graph for this function:

The documentation for this struct was generated from the following file: