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 391 of file array_list.hpp.

391 {
392 ensure(elements.head, "NOT INITIALIZED");
393 return elements[index];
394 }
#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 381 of file array_list.hpp.

381 {
382 ensure(elements.head, "NOT INITIALIZED");
383 return elements[index];
384 }

◆ capacity()

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

Array list capacity.

Returns
capacity of array list

Definition at line 199 of file array_list.hpp.

199 {
200 ensure(count <= elements.len, "COUNT EXCEEDS SLICE SIZE!");
201 return elements.len;
202 }
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 122 of file array_list.hpp.

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

◆ init() [1/2]

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

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 )
inlinenodiscardnoexcept

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.

97 {
98 ensure(elements.head == nullptr && elements.size() == 0, "ALREADY INITIALIZED!");
99 if (capacity < init.size()) {
100 capacity = init.size();
101 }
102 capacity = capacity ? capacity : 10;
103 auto allocRes = alloc.create_many<T>(init.size());
104 if (allocRes.is_error()) {
105 return allocRes.error();
106 }
107
108 elements = *allocRes;
109 size_t index = 0;
110 for (const auto &elem: init) {
111 elements[index++] = elem;
112 }
113 count = index;
114
115 return success();
116 }
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 411 of file array_list.hpp.

411 {
412 ensure(elements.head, "NOT INITIALIZED");
413 return elements[index];
414 }

◆ 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 401 of file array_list.hpp.

401 {
402 ensure(elements.head, "NOT INITIALIZED");
403 return elements[index];
404 }

◆ 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 367 of file array_list.hpp.

367 {
368 ensure(elements.head, "NOT INITIALIZED");
369 if (count == 0) {
370 return nullopt;
371 }
372 --count;
373 return elements[count];
374 }
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 )
inlinenodiscardnoexcept

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 138 of file array_list.hpp.

139 {
140 ensure(elements.head, "NOT INITIALIZED");
141 if (count + elems.size() >= elements.len) {
142 size_t newSize = elements.len + std::max(((elements.len + 1) / 2), elems.size());
143 if (auto res = reserve(alloc, newSize); res.is_error()) {
144 return res;
145 }
146 }
147
148 ensure(push(elems).is_success(), "SOMEHOW GIVING MORE SPACE DIDN'T WORK");
149 return success();
150 }
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 )
inlinenodiscardnoexcept

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 160 of file array_list.hpp.

161 {
162 return push(alloc, elems.to_const());
163 }
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 )
inlinenodiscardnoexcept

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 173 of file array_list.hpp.

173 {
174 ensure(elements.head, "NOT INITIALIZED");
175 if (count >= elements.len) {
176 size_t newSize = elements.len + ((elements.len + 1) / 2);
177 if (auto res = reserve(alloc, newSize); res.is_error()) {
178 return res;
179 }
180 }
181
182 ensure(push(elem).is_success(), "SOMEHOW GIVING MORE SPACE DIDN'T WORK");
183 return success();
184 }
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)
inlinenodiscardnoexcept

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 276 of file array_list.hpp.

276 {
277 ensure(elements.head, "NOT INITIALIZED");
278 if (count + elems.size() > elements.len) {
280 }
281
282 for (size_t i = 0; i < elems.size(); ++i) {
283 elements[count++] = elems[i];
284 }
285
286 return success();
287 }
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)
inlinenodiscardnoexcept

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 266 of file array_list.hpp.

266 {
267 return push(elems.to_const());
268 }
Here is the call graph for this function:

◆ push() [6/6]

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

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 295 of file array_list.hpp.

295 {
296 ensure(elements.head, "NOT INITIALIZED");
297 if (count >= elements.len) {
299 }
300
301 elements[count++] = elem;
302 return success();
303 }
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 )
inlinenodiscardnoexcept

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 210 of file array_list.hpp.

210 {
211 ensure(elements.head, "NOT INITIALIZED");
212 ensure(count <= elements.len, "COUNT EXCEEDS SLICE SIZE!");
213 if (newSize <= capacity()) {
214 return success();
215 }
216 ensure(newSize > size(), "FAILED TO GROW");
217 auto newElemAllocRes = alloc.create_many<T>(newSize);
218 if (newElemAllocRes.is_error()) {
219 return newElemAllocRes.error();
220 }
221
223 for (size_t i = 0; i < elements.size(); ++i) {
224 std::swap(newElems[i], elements[i]);
225 }
226 alloc.destroy_many(elements);
227 elements = newElems;
228 return success();
229 }
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 354 of file array_list.hpp.

354 {
355 ensure(elements.head, "NOT INITIALIZED");
356 if (count == 0) {
357 return nullopt;
358 }
359 return shift_remove(0);
360 }
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 445 of file array_list.hpp.

445 {
446 ensure(elements.head, "NOT INITIALIZED");
447 ensure(index < count, "ARRAY OUT OF BOUNDS DETECTED!");
448
449 for (size_t i = index; i + 1 < count; ++i) {
450 std::swap(elements[index], elements[index + 1]);
451 }
452 auto popRes = pop();
453 ensure(popRes, "COULDN'T REMOVE ELMENT FROM NON-EMPTY LIST");
454 return *popRes;
455 }
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)
inlinenodiscardnoexcept

Will shrink the capacity to match the current size.

Parameters
allocAllocator to use to resize
Returns
Result

Definition at line 236 of file array_list.hpp.

236 {
237 ensure(elements.head, "NOT INITIALIZED");
238 ensure(count <= elements.len, "COUNT EXCEEDS SLICE SIZE!");
239 auto newSize = size();
240 if (newSize == capacity()) {
241 return success();
242 }
243
244 ensure(newSize < size(), "FAILED TO SHRINK");
245 auto newElemAllocRes = alloc.create_many<T>(newSize);
246 if (!newElemAllocRes) {
247 return newElemAllocRes;
248 }
249
251 for (size_t i = 0; i < elements.size(); ++i) {
252 std::swap(newElems[i], elements[i]);
253 }
254 alloc.destroy_many(elements);
255 elements = newElems;
256 return success();
257 }
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 190 of file array_list.hpp.

190 {
191 ensure(count <= elements.len, "COUNT EXCEEDS SLICE SIZE!");
192 return count;
193 }
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 460 of file array_list.hpp.

460{ 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 465 of file array_list.hpp.

465{ return elements.sub(0, count).to_const(); }
Here is the call graph for this function:

◆ 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 424 of file array_list.hpp.

424 {
425 ensure(elements.head, "NOT INITIALIZED");
426 ensure(index < count, "ARRAY OUT OF BOUNDS DETECTED!");
427 auto end = count - 1;
428 if (index != end) {
429 std::swap(elements[end], elements[index]);
430 }
431
432 auto popRes = pop();
433 ensure(popRes.has_value(), "COULDN'T REMOVE ELMENT FROM NON-EMPTY LIST");
434 return *popRes;
435 }
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 )
inlinenodiscardnoexcept

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 334 of file array_list.hpp.

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

◆ unshift() [2/2]

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

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 311 of file array_list.hpp.

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

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