RPNX::DataStructures
Header-only C++ data structures and supporting utilities.
Loading...
Searching...
No Matches
dynar.hpp
1// Copyright (c) 2026 Ryan P. Nicholl <rnicholl@protonmail.com>
2
3#ifndef RPNXDATASTRUCTURES_DYNAR_HPP
4#define RPNXDATASTRUCTURES_DYNAR_HPP
5
6#include <compare>
7#include <initializer_list>
8#include <memory>
9#include <type_traits>
10#include <utility>
11#include <vector>
12
13namespace rpnx
14{
27 template < typename T, typename Allocator = std::allocator< T > >
28 class dynar
29 {
30 public:
32 using underlying_type = std::vector< T, Allocator >;
34 using value_type = typename underlying_type::value_type;
36 using allocator_type = typename underlying_type::allocator_type;
38 using size_type = typename underlying_type::size_type;
40 using difference_type = typename underlying_type::difference_type;
42 using reference = typename underlying_type::reference;
44 using const_reference = typename underlying_type::const_reference;
46 using pointer = typename underlying_type::pointer;
48 using const_pointer = typename underlying_type::const_pointer;
50 using iterator = typename underlying_type::iterator;
52 using const_iterator = typename underlying_type::const_iterator;
54 using reverse_iterator = typename underlying_type::reverse_iterator;
56 using const_reverse_iterator = typename underlying_type::const_reverse_iterator;
57
58 private:
59 underlying_type m_vector;
60
61 public:
65 dynar() = default;
66
71 explicit dynar(Allocator const& alloc) : m_vector(alloc)
72 {
73 }
74
80 explicit dynar(size_type count, Allocator const& alloc = Allocator()) : m_vector(count, alloc)
81 {
82 }
83
90 dynar(size_type count, T const& value, Allocator const& alloc = Allocator()) : m_vector(count, value, alloc)
91 {
92 }
93
101 template < typename InputIt >
102 dynar(InputIt first, InputIt last, Allocator const& alloc = Allocator()) : m_vector(first, last, alloc)
103 {
104 }
105
109 dynar(dynar const&) = default;
110
114 dynar(dynar&&) noexcept(std::is_nothrow_move_constructible_v< underlying_type >) = default;
115
121 dynar(dynar const& other, Allocator const& alloc) : m_vector(other.m_vector, alloc)
122 {
123 }
124
130 dynar(dynar&& other, Allocator const& alloc) : m_vector(std::move(other.m_vector), alloc)
131 {
132 }
133
139 dynar(std::initializer_list< T > init, Allocator const& alloc = Allocator()) : m_vector(init, alloc)
140 {
141 }
142
147 dynar& operator=(dynar const&) = default;
148
153 dynar& operator=(dynar&&) noexcept(std::is_nothrow_move_assignable_v< underlying_type >) = default;
154
160 dynar& operator=(std::initializer_list< T > init)
161 {
162 m_vector = init;
163 return *this;
164 }
165
171 void assign(size_type count, T const& value)
172 {
173 m_vector.assign(count, value);
174 }
175
182 template < typename InputIt >
183 void assign(InputIt first, InputIt last)
184 {
185 m_vector.assign(first, last);
186 }
187
192 void assign(std::initializer_list< T > init)
193 {
194 m_vector.assign(init);
195 }
196
202 {
203 return m_vector.get_allocator();
204 }
205
213 {
214 return m_vector.at(pos);
215 }
216
219 {
220 return m_vector.at(pos);
221 }
222
230 {
231 return m_vector[pos];
232 }
233
236 {
237 return m_vector[pos];
238 }
239
246 {
247 return m_vector.front();
248 }
249
252 {
253 return m_vector.front();
254 }
255
262 {
263 return m_vector.back();
264 }
265
268 {
269 return m_vector.back();
270 }
271
277 T* data() noexcept
278 {
279 return m_vector.data();
280 }
281
283 T const* data() const noexcept
284 {
285 return m_vector.data();
286 }
287
289 iterator begin() noexcept
290 {
291 return m_vector.begin();
292 }
293
295 const_iterator begin() const noexcept
296 {
297 return m_vector.begin();
298 }
299
301 const_iterator cbegin() const noexcept
302 {
303 return m_vector.cbegin();
304 }
305
307 iterator end() noexcept
308 {
309 return m_vector.end();
310 }
311
313 const_iterator end() const noexcept
314 {
315 return m_vector.end();
316 }
317
319 const_iterator cend() const noexcept
320 {
321 return m_vector.cend();
322 }
323
326 {
327 return m_vector.rbegin();
328 }
329
332 {
333 return m_vector.rbegin();
334 }
335
338 {
339 return m_vector.crbegin();
340 }
341
344 {
345 return m_vector.rend();
346 }
347
350 {
351 return m_vector.rend();
352 }
353
356 {
357 return m_vector.crend();
358 }
359
361 bool empty() const noexcept
362 {
363 return m_vector.empty();
364 }
365
367 size_type size() const noexcept
368 {
369 return m_vector.size();
370 }
371
373 size_type max_size() const noexcept
374 {
375 return m_vector.max_size();
376 }
377
384 void reserve(size_type new_cap)
385 {
386 m_vector.reserve(new_cap);
387 }
388
390 size_type capacity() const noexcept
391 {
392 return m_vector.capacity();
393 }
394
401 {
402 m_vector.shrink_to_fit();
403 }
404
406 void clear() noexcept
407 {
408 m_vector.clear();
409 }
410
417 iterator insert(const_iterator pos, T const& value)
418 {
419 return m_vector.insert(pos, value);
420 }
421
429 {
430 return m_vector.insert(pos, std::move(value));
431 }
432
440 iterator insert(const_iterator pos, size_type count, T const& value)
441 {
442 return m_vector.insert(pos, count, value);
443 }
444
453 template < typename InputIt >
454 iterator insert(const_iterator pos, InputIt first, InputIt last)
455 {
456 return m_vector.insert(pos, first, last);
457 }
458
465 iterator insert(const_iterator pos, std::initializer_list< T > init)
466 {
467 return m_vector.insert(pos, init);
468 }
469
477 template < typename... Args >
478 iterator emplace(const_iterator pos, Args&&... args)
479 {
480 return m_vector.emplace(pos, std::forward< Args >(args)...);
481 }
482
489 {
490 return m_vector.erase(pos);
491 }
492
500 {
501 return m_vector.erase(first, last);
502 }
503
505 void push_back(T const& value)
506 {
507 m_vector.push_back(value);
508 }
509
511 void push_back(T&& value)
512 {
513 m_vector.push_back(std::move(value));
514 }
515
522 template < typename... Args >
523 reference emplace_back(Args&&... args)
524 {
525 return m_vector.emplace_back(std::forward< Args >(args)...);
526 }
527
529 void pop_back()
530 {
531 m_vector.pop_back();
532 }
533
538 void resize(size_type count)
539 {
540 m_vector.resize(count);
541 }
542
548 void resize(size_type count, T const& value)
549 {
550 m_vector.resize(count, value);
551 }
552
554 void swap(dynar& other) noexcept(noexcept(m_vector.swap(other.m_vector)))
555 {
556 m_vector.swap(other.m_vector);
557 }
558
560 template < typename U, typename A >
561 friend bool operator==(dynar< U, A > const& lhs, dynar< U, A > const& rhs);
562
564 template < typename U, typename A >
565 friend bool operator<(dynar< U, A > const& lhs, dynar< U, A > const& rhs);
566
568 template < typename U, typename A >
569 friend auto operator<=>(dynar< U, A > const& lhs, dynar< U, A > const& rhs) -> decltype(std::declval< typename dynar< U, A >::underlying_type const& >() <=> std::declval< typename dynar< U, A >::underlying_type const& >());
570 };
571
577 template < typename T, typename Allocator >
578 void swap(dynar< T, Allocator >& lhs, dynar< T, Allocator >& rhs) noexcept(noexcept(lhs.swap(rhs)))
579 {
580 lhs.swap(rhs);
581 }
582
589 template < typename T, typename Allocator >
591 {
592 return lhs.m_vector == rhs.m_vector;
593 }
594
601 template < typename T, typename Allocator >
603 {
604 return !(lhs == rhs);
605 }
606
613 template < typename T, typename Allocator >
615 {
616 if (lhs.size() != rhs.size())
617 {
618 return lhs.size() < rhs.size();
619 }
620
621 return lhs.m_vector < rhs.m_vector;
622 }
623
630 template < typename T, typename Allocator >
632 {
633 return rhs < lhs;
634 }
635
642 template < typename T, typename Allocator >
644 {
645 return !(rhs < lhs);
646 }
647
654 template < typename T, typename Allocator >
656 {
657 return !(lhs < rhs);
658 }
659
666 template < typename T, typename Allocator >
667 auto operator<=>(dynar< T, Allocator > const& lhs, dynar< T, Allocator > const& rhs) -> decltype(std::declval< typename dynar< T, Allocator >::underlying_type const& >() <=> std::declval< typename dynar< T, Allocator >::underlying_type const& >())
668 {
669 using ordering_type = decltype(lhs.m_vector <=> rhs.m_vector);
670
671 if (lhs.size() < rhs.size())
672 {
673 return ordering_type::less;
674 }
675
676 if (rhs.size() < lhs.size())
677 {
678 return ordering_type::greater;
679 }
680
681 return lhs.m_vector <=> rhs.m_vector;
682 }
683} // namespace rpnx
684
685#endif // RPNXDATASTRUCTURES_DYNAR_HPP
Dynamic array container with size-first ordering.
Definition dynar.hpp:29
dynar(Allocator const &alloc)
Constructs an empty dynar with an allocator.
Definition dynar.hpp:71
typename underlying_type::const_reverse_iterator const_reverse_iterator
Immutable reverse-iterator type.
Definition dynar.hpp:56
typename underlying_type::reverse_iterator reverse_iterator
Mutable reverse-iterator type.
Definition dynar.hpp:54
dynar(size_type count, T const &value, Allocator const &alloc=Allocator())
Constructs a dynar containing count copies of value.
Definition dynar.hpp:90
void assign(InputIt first, InputIt last)
Assigns an iterator range.
Definition dynar.hpp:183
dynar(size_type count, Allocator const &alloc=Allocator())
Constructs a dynar containing count default-inserted elements.
Definition dynar.hpp:80
void assign(std::initializer_list< T > init)
Assigns an initializer list.
Definition dynar.hpp:192
reverse_iterator rbegin() noexcept
Returns a reverse iterator to the last element.
Definition dynar.hpp:325
const_iterator cbegin() const noexcept
Returns an immutable iterator to the first element.
Definition dynar.hpp:301
void swap(dynar &other) noexcept(noexcept(m_vector.swap(other.m_vector)))
Exchanges contents with another dynar.
Definition dynar.hpp:554
T * data() noexcept
Returns a pointer to the contiguous element storage.
Definition dynar.hpp:277
allocator_type get_allocator() const noexcept
Returns a copy of the allocator associated with the container.
Definition dynar.hpp:201
T const * data() const noexcept
Returns a pointer to the contiguous element storage.
Definition dynar.hpp:283
typename underlying_type::const_iterator const_iterator
Immutable random-access iterator type.
Definition dynar.hpp:52
dynar(dynar &&) noexcept(std::is_nothrow_move_constructible_v< underlying_type >)=default
Move-constructs a dynar.
typename underlying_type::difference_type difference_type
Signed type used for iterator distances.
Definition dynar.hpp:40
iterator begin() noexcept
Returns an iterator to the first element.
Definition dynar.hpp:289
void clear() noexcept
Removes all elements without reducing capacity.
Definition dynar.hpp:406
typename underlying_type::const_reference const_reference
Immutable element reference type.
Definition dynar.hpp:44
bool empty() const noexcept
Returns whether the container has no elements.
Definition dynar.hpp:361
size_type size() const noexcept
Returns the number of stored elements.
Definition dynar.hpp:367
typename underlying_type::reference reference
Mutable element reference type.
Definition dynar.hpp:42
typename underlying_type::size_type size_type
Unsigned type used for sizes and indices.
Definition dynar.hpp:38
const_reverse_iterator rend() const noexcept
Returns an immutable reverse iterator preceding the first element.
Definition dynar.hpp:349
const_iterator cend() const noexcept
Returns an immutable iterator one past the last element.
Definition dynar.hpp:319
reference at(size_type pos)
Returns the element at an index with bounds checking.
Definition dynar.hpp:212
size_type max_size() const noexcept
Returns the maximum number of elements supported by the implementation.
Definition dynar.hpp:373
typename underlying_type::iterator iterator
Mutable random-access iterator type.
Definition dynar.hpp:50
void resize(size_type count)
Changes the number of elements, value-initializing new elements.
Definition dynar.hpp:538
const_iterator begin() const noexcept
Returns an immutable iterator to the first element.
Definition dynar.hpp:295
iterator insert(const_iterator pos, T &&value)
Inserts an element by moving it before a position.
Definition dynar.hpp:428
typename underlying_type::pointer pointer
Mutable element pointer type.
Definition dynar.hpp:46
const_reference at(size_type pos) const
Returns the element at an index with bounds checking.
Definition dynar.hpp:218
iterator insert(const_iterator pos, T const &value)
Inserts a copy of an element before a position.
Definition dynar.hpp:417
const_reference back() const
Returns the last element.
Definition dynar.hpp:267
friend bool operator<(dynar< U, A > const &lhs, dynar< U, A > const &rhs)
Grants the less-than comparison access to the underlying container.
dynar()=default
Constructs an empty dynar.
void pop_back()
Removes the last element.
Definition dynar.hpp:529
dynar & operator=(dynar &&) noexcept(std::is_nothrow_move_assignable_v< underlying_type >)=default
Move-assigns another dynar.
reference back()
Returns the last element.
Definition dynar.hpp:261
friend auto operator<=>(dynar< U, A > const &lhs, dynar< U, A > const &rhs) -> decltype(std::declval< typename dynar< U, A >::underlying_type const & >()<=> std::declval< typename dynar< U, A >::underlying_type const & >())
Grants the three-way comparison access to the underlying container.
void resize(size_type count, T const &value)
Changes the number of elements, copying a value for new elements.
Definition dynar.hpp:548
typename underlying_type::const_pointer const_pointer
Immutable element pointer type.
Definition dynar.hpp:48
reference emplace_back(Args &&... args)
Constructs an element at the end of the container.
Definition dynar.hpp:523
const_reference front() const
Returns the first element.
Definition dynar.hpp:251
dynar(dynar const &)=default
Copy-constructs a dynar.
reverse_iterator rend() noexcept
Returns a reverse iterator preceding the first element.
Definition dynar.hpp:343
typename underlying_type::value_type value_type
Stored element type.
Definition dynar.hpp:34
iterator emplace(const_iterator pos, Args &&... args)
Constructs an element in place before a position.
Definition dynar.hpp:478
void shrink_to_fit()
Requests that unused capacity be released.
Definition dynar.hpp:400
iterator insert(const_iterator pos, InputIt first, InputIt last)
Inserts an iterator range before a position.
Definition dynar.hpp:454
const_reverse_iterator crend() const noexcept
Returns an immutable reverse iterator preceding the first element.
Definition dynar.hpp:355
iterator insert(const_iterator pos, size_type count, T const &value)
Inserts repeated copies of an element before a position.
Definition dynar.hpp:440
iterator erase(const_iterator pos)
Erases the element at a position.
Definition dynar.hpp:488
const_reverse_iterator rbegin() const noexcept
Returns an immutable reverse iterator to the last element.
Definition dynar.hpp:331
dynar(InputIt first, InputIt last, Allocator const &alloc=Allocator())
Constructs a dynar from an iterator range.
Definition dynar.hpp:102
void assign(size_type count, T const &value)
Assigns count copies of value.
Definition dynar.hpp:171
reference front()
Returns the first element.
Definition dynar.hpp:245
reference operator[](size_type pos)
Returns the element at an index without bounds checking.
Definition dynar.hpp:229
size_type capacity() const noexcept
Returns the number of elements that fit without reallocating.
Definition dynar.hpp:390
const_reverse_iterator crbegin() const noexcept
Returns an immutable reverse iterator to the last element.
Definition dynar.hpp:337
typename underlying_type::allocator_type allocator_type
Allocator type used to manage storage.
Definition dynar.hpp:36
const_iterator end() const noexcept
Returns an immutable iterator one past the last element.
Definition dynar.hpp:313
iterator end() noexcept
Returns an iterator one past the last element.
Definition dynar.hpp:307
friend bool operator==(dynar< U, A > const &lhs, dynar< U, A > const &rhs)
Grants the equality comparison access to the underlying container.
const_reference operator[](size_type pos) const
Returns the element at an index without bounds checking.
Definition dynar.hpp:235
iterator erase(const_iterator first, const_iterator last)
Erases an iterator range.
Definition dynar.hpp:499
void push_back(T &&value)
Appends an element by moving it.
Definition dynar.hpp:511
dynar & operator=(dynar const &)=default
Copy-assigns another dynar.
dynar(dynar &&other, Allocator const &alloc)
Move-constructs a dynar using the specified allocator.
Definition dynar.hpp:130
void reserve(size_type new_cap)
Ensures storage is available for at least a requested number of elements.
Definition dynar.hpp:384
dynar(std::initializer_list< T > init, Allocator const &alloc=Allocator())
Constructs a dynar from an initializer list.
Definition dynar.hpp:139
iterator insert(const_iterator pos, std::initializer_list< T > init)
Inserts an initializer list before a position.
Definition dynar.hpp:465
void push_back(T const &value)
Appends a copy of an element.
Definition dynar.hpp:505
std::vector< T, Allocator > underlying_type
Underlying contiguous container type.
Definition dynar.hpp:32
Containers, iterator adapters, callable wrappers, and value utilities.
Definition annex.hpp:14
void swap(annex< T, Alloc > &lhs, annex< T, Alloc > &rhs) noexcept(noexcept(lhs.swap(rhs)))
Swaps two annex objects.
Definition annex.hpp:577
bool operator<=(annex< T, Alloc > const &lhs, annex< T, Alloc > const &rhs)
Orders two annex objects.
Definition annex.hpp:651
bool operator>=(annex< T, Alloc > const &lhs, annex< T, Alloc > const &rhs)
Orders two annex objects.
Definition annex.hpp:663
bool operator<(annex< T, Alloc > const &lhs, annex< T, Alloc > const &rhs)
Orders two annex objects.
Definition annex.hpp:627
bool operator!=(annex< T, Alloc > const &lhs, annex< T, Alloc > const &rhs)
Compares two annex objects for inequality.
Definition annex.hpp:615
bool operator>(annex< T, Alloc > const &lhs, annex< T, Alloc > const &rhs)
Orders two annex objects.
Definition annex.hpp:639
auto operator<=>(annex< T, Alloc > const &lhs, annex< T, Alloc > const &rhs) -> decltype(*lhs<=> *rhs)
Three-way compares two annex objects when T supports <=>.
Definition annex.hpp:676
bool operator==(annex< T, Alloc > const &lhs, annex< T, Alloc > const &rhs)
Compares two annex objects for equality.
Definition annex.hpp:598