tenno 0.1.0
Loading...
Searching...
No Matches
vector.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// Author: Giovanni Santini
3// Mail: giovanni.santini@proton.me
4// Github: @San7o
5
6#pragma once
7
8#include <initializer_list>
9#include <tenno/algorithm.hpp>
10#include <tenno/error.hpp>
11#include <tenno/expected.hpp>
12#include <tenno/functional.hpp>
13#include <tenno/memory.hpp>
14#include <tenno/ranges.hpp>
15#include <tenno/types.hpp>
16#include <utility> // std::forward
17
18namespace tenno
19{
20
21template <class T, class Allocator = tenno::allocator<T>> class vector
22{
23public:
24 using value_type = T;
25 using allocator_type = Allocator;
28 using const_reference = const value_type &;
29 using pointer = typename Allocator::pointer;
30 using const_pointer = typename Allocator::const_pointer;
31 using difference_type = T;
32
34 : _size(0), _capacity(0), _data(nullptr),
35 _allocator(tenno::allocator<T>()) {};
36
37 explicit vector(size_type count,
38
39 const T &value, const Allocator &alloc = Allocator())
40 : _size(count), _capacity(count), _data(_allocator.allocate(count)),
41 _allocator(alloc)
42 {
43 for (size_type i = 0; i < count; ++i)
44 {
45 _data[i] = value;
46 }
47 }
48 explicit vector(size_type count, const Allocator &alloc = Allocator())
49 : _size(count), _capacity(count), _data(_allocator.allocate(count)),
50 _allocator(alloc)
51 {
52 }
53
54 vector(const vector &other)
55 : _size(other._size), _capacity(other._capacity),
56 _data(_allocator.allocate(other._size)), _allocator(other._allocator)
57 {
58 for (size_type i = 0; i < other._size; ++i)
59 {
60 _data[i] = other._data[i];
61 }
62 }
63
64 vector(const vector &other, const Allocator &alloc)
65 : _size(other._size), _capacity(other._capacity),
66 _data(_allocator.allocate(other._size)), _allocator(alloc)
67 {
68 for (size_type i = 0; i < other._size; ++i)
69 {
70 _data[i] = other._data[i];
71 }
72 }
73
74 vector(vector &&other)
75 : _size(other._size), _capacity(other._capacity), _data(other._data),
76 _allocator(other._allocator)
77 {
78 other._size = 0;
79 other._data = nullptr;
80 }
81
82 vector(vector &&other, const Allocator &alloc)
83 : _size(other._size), _capacity(other._capacity), _data(other._data),
84 _allocator(alloc)
85 {
86 other._size = 0;
87 other._data = nullptr;
88 }
89 vector(std::initializer_list<T> init, const Allocator &alloc = Allocator())
90 : _size(init.size()), _capacity(init.size()),
91 _data(_allocator.allocate(init.size())), _allocator(alloc)
92 {
93 size_type i = 0;
94 for (auto it = init.begin(); it != init.end(); ++it)
95 {
96 _data[i] = *it;
97 ++i;
98 }
99 }
100
102 {
103 if (_data == nullptr)
104 return;
105 _allocator.deallocate(_data, _size);
106 }
107
108 vector &operator=(const vector &other)
109 {
110 if (this != &other)
111 {
112 _allocator.deallocate(_data, _capacity);
113 _size = other._size;
114 _capacity = other._size;
115 _allocator = other._allocator;
116 _data = _allocator.allocate(_size);
117 for (size_type i = 0; i < _size; ++i)
118 {
119 _data[i] = other._data[i];
120 }
121 }
122 return *this;
123 }
124
125 vector &operator=(vector &&other) noexcept
126 {
127 if (this != &other)
128 {
129 _allocator.deallocate(_data, _capacity);
130 _size = other._size;
131 _capacity = other._capacity;
132 _data = other._data;
133 _allocator = other._allocator;
134
135 other._size = 0;
136 other._data = nullptr;
137 other._capacity = 0;
138 }
139 return *this;
140 }
141
142 vector &operator=(std::initializer_list<value_type> ilist)
143 {
144 _allocator.deallocate(_data, _capacity);
145 _size = ilist.size();
146 _capacity = ilist.size();
147 _data = _allocator.allocate(_size);
148 size_type i = 0;
149 for (auto it = ilist.begin(); it != ilist.end(); ++it)
150 {
151 _data[i] = *it;
152 ++i;
153 }
154 return *this;
155 }
156
157 void assign(size_type count, const T &value)
158 {
159 if (count > _capacity)
160 {
161 _allocator.deallocate(_data, _capacity);
162 _size = count;
163 _capacity = count;
164 _data = _allocator.allocate(_size);
165 }
166 for (size_type i = 0; i < count; ++i)
167 {
168 _data[i] = value;
169 }
170 }
171
172 /*
173 // this overwrites the previous assign method
174 template< class InputIt >
175 void assign( InputIt first, InputIt last )
176 {
177 size_type count = 0;
178 InputIt tmp = first;
179 while (tmp != last)
180 {
181 count++;
182 tmp++;
183 }
184
185 if (count > _capacity)
186 {
187 _allocator.deallocate(_data, _capacity);
188 _size = count;
189 _capacity = count;
190 _data = _allocator.allocate(_size);
191 }
192 size_type i = 0;
193 for (auto it = first; it != last; ++it)
194 {
195 _data[i] = *it;
196 ++i;
197 }
198 }
199 */
200
201 void assign(std::initializer_list<T> ilist)
202 {
203 _allocator.deallocate(_data, _capacity);
204 _size = ilist.size();
205 _capacity = ilist.size();
206 _data = _allocator.allocate(_size);
207 size_type i = 0;
208 for (auto it = ilist.begin(); it != ilist.end(); ++it)
209 {
210 _data[i] = *it;
211 ++i;
212 }
213 }
214
216 {
217 if (r.size() > _capacity)
218 {
219 _allocator.deallocate(_data, _capacity);
220 _size = r.size();
221 _capacity = r.size();
222 _data = _allocator.allocate(_size);
223 }
224 size_type i = 0;
225 for (auto it = r.begin(); it != r.end(); ++it)
226 {
227 _data[i] = *it;
228 ++i;
229 }
230 }
231
233 {
234 return this->_allocator;
235 }
236
238 {
239 if (pos >= _size)
240 {
242 }
243 return tenno::reference_wrapper<T>(tenno::move(_data[pos]));
244 }
245
247 {
248 if (pos >= _size)
249 {
251 }
252 if (_data == nullptr)
253 {
255 }
256 return tenno::reference_wrapper<T>(tenno::move(_data[pos]));
257 }
258
261 {
262 if (pos >= _size)
263 {
265 }
266 if (_data == nullptr)
267 {
269 }
271 }
272
274 {
275 if (_size == 0)
276 {
278 }
279 if (_data == nullptr)
280 {
282 }
284 }
285
287 {
288 if (_size == 0)
289 {
291 }
292 if (_data == nullptr)
293 {
295 }
296 return tenno::reference_wrapper<const T>(tenno::move(_data[_size - 1]));
297 }
298
300 {
301 if (_data == nullptr)
302 {
304 }
305 return _data;
306 }
307
309 {
310 if (_data == nullptr)
311 {
313 }
314 return _data;
315 }
316
320 struct iterator
321 {
322 using iterator_category = std::forward_iterator_tag;
323 using difference_type = std::ptrdiff_t;
324 using value_type = T;
325 using pointer = T *;
326 using reference = T &;
327
330
332 const tenno::size _index)
333 : index(_index), vec(_vec)
334 {
335 }
336
338 {
339 index++;
340 return *this;
341 }
342
344 {
345 iterator _iterator = *this;
346 ++index;
347 return _iterator;
348 }
349
350 bool operator==(const iterator &other) const noexcept
351 {
352 return index == other.index;
353 }
354
355 bool operator!=(const iterator &other) const noexcept
356 {
357 return !(index == other.index);
358 }
359
361 operator*() noexcept
362 {
363 return vec[index];
364 }
365
367 operator->() noexcept
368 {
369 return vec[index];
370 }
371
376 };
377
389 iterator begin() noexcept
390 {
391 return iterator(*this, tenno::size(0));
392 }
393
404 iterator end() noexcept
405 {
406 return iterator(*this, this->_size);
407 }
408
413 {
414 using reverse_iterator_category = std::forward_iterator_tag;
415 using difference_type = std::ptrdiff_t;
416 using value_type = T;
417 using pointer = T *;
418 using reference = T &;
419
420 long long int index;
422
424 const long long int _index)
425 : index(_index), vec(_vec)
426 {
427 }
428
430 {
431 index--;
432 return *this;
433 }
434
436 {
437 reverse_iterator _iterator = *this;
438 --index;
439 return _iterator;
440 }
441
442 bool operator==(const reverse_iterator &other) const noexcept
443 {
444 return index == other.index;
445 }
446
447 bool operator!=(const reverse_iterator &other) const noexcept
448 {
449 return !(index == other.index);
450 }
451
453 operator*() noexcept
454 {
455 return vec[index];
456 }
457
459 operator->() noexcept
460 {
461 return vec[index];
462 }
463
468 };
469
482 {
483 return reverse_iterator(*this, _size - 1);
484 }
485
497 {
498 return reverse_iterator(*this, -1);
499 }
500
501 bool empty() const noexcept
502 {
503 return _size == 0;
504 }
505
506 size_type size() const noexcept
507 {
508 return _size;
509 }
510
511 size_type max_size() const noexcept
512 {
513 return (tenno::size) -1;
514 }
515
516 void reserve(size_type new_cap)
517 {
518 if (new_cap <= _capacity)
519 {
520 return;
521 }
522 pointer new_data = _allocator.allocate(new_cap);
523 for (size_type i = 0; i < _size; ++i)
524 {
525 new_data[i] = _data[i];
526 }
527 _allocator.deallocate(_data, _capacity);
528 _data = new_data;
529 _capacity = new_cap;
530 }
531
532 size_type capacity() const noexcept
533 {
534 return _capacity;
535 }
536
537 void shrink_to_fit() noexcept
538 {
539 if (_size == _capacity)
540 {
541 return;
542 }
543 pointer new_data = _allocator.allocate(_size);
544 for (size_type i = 0; i < _size; ++i)
545 {
546 new_data[i] = _data[i];
547 }
548 _allocator.deallocate(_data, _capacity);
549 _data = new_data;
550 _capacity = _size;
551 }
552
553 void clear() noexcept
554 {
555 this->_size = 0;
556 }
557
558 void push_back(const T &value) noexcept
559 {
560 if (_size == _capacity)
561 {
562 reserve(_capacity == 0 ? 1 : _capacity * 2);
563 }
564 _data[_size] = value;
565 _size++;
566 }
567
568 void push_back(const T &&value) noexcept
569 {
570 push_back(value);
571 }
572
573 template <class... Args> reference emplace_back(Args &&...args) noexcept
574 {
575 push_back(T(std::forward<Args>(args)...));
576 return _data[_size - 1];
577 }
578
579 void pop_back() noexcept
580 {
581 if (_size == 0)
582 {
583 return;
584 }
585 _size--;
586 }
587
588 void resize(size_type count) noexcept
589 {
590 reserve(count);
591 while (_size < count)
592 {
593 _data[_size] = T();
594 ++_size;
595 }
596 _size = count;
597 }
598
599 void resize(size_type count, const value_type &value) noexcept
600 {
601 reserve(count);
602 while (_size < count)
603 {
604 _data[_size] = value;
605 ++_size;
606 }
607 _size = count;
608 }
609
610 void swap(vector &other) noexcept
611 {
612 tenno::swap(_size, other._size);
613 tenno::swap(_capacity, other._capacity);
614 tenno::swap(_data, other._data);
615 tenno::swap(_allocator, other._allocator);
616 }
617
618private:
619 size_type _size;
620 size_type _capacity;
621 pointer _data;
622 Allocator _allocator;
623};
624
625} // namespace tenno
An expected value.
Definition expected.hpp:38
A range of elements.
Definition ranges.hpp:21
constexpr iterator begin() const noexcept
Definition ranges.hpp:76
constexpr tenno::size size() const noexcept
Definition ranges.hpp:34
constexpr iterator end() const noexcept
Definition ranges.hpp:81
A reference wrapper class.
An unexpected value.
Definition expected.hpp:20
expected< tenno::reference_wrapper< const T >, tenno::error > operator[](size_type pos) const
Definition vector.hpp:260
vector(vector &&other)
Definition vector.hpp:74
void pop_back() noexcept
Definition vector.hpp:579
void push_back(const T &&value) noexcept
Definition vector.hpp:568
vector(size_type count, const Allocator &alloc=Allocator())
Definition vector.hpp:48
size_type max_size() const noexcept
Definition vector.hpp:511
expected< tenno::reference_wrapper< const T >, tenno::error > front() const
Definition vector.hpp:273
reverse_iterator rbegin() noexcept
Get an reverse_iterator to the beginning of the data.
Definition vector.hpp:481
void push_back(const T &value) noexcept
Definition vector.hpp:558
tenno::expected< const_pointer, tenno::error > data() const noexcept
Definition vector.hpp:308
expected< tenno::reference_wrapper< T >, tenno::error > operator[](size_type pos)
Definition vector.hpp:246
expected< tenno::reference_wrapper< T >, tenno::error > at(size_type pos)
Definition vector.hpp:237
size_type capacity() const noexcept
Definition vector.hpp:532
size_type size() const noexcept
Definition vector.hpp:506
void assign(std::initializer_list< T > ilist)
Definition vector.hpp:201
allocator_type get_allocator() const
Definition vector.hpp:232
value_type & reference
Definition vector.hpp:27
vector & operator=(vector &&other) noexcept
Definition vector.hpp:125
typename Allocator::pointer pointer
Definition vector.hpp:29
void reserve(size_type new_cap)
Definition vector.hpp:516
vector(const vector &other, const Allocator &alloc)
Definition vector.hpp:64
void resize(size_type count) noexcept
Definition vector.hpp:588
void shrink_to_fit() noexcept
Definition vector.hpp:537
void clear() noexcept
Definition vector.hpp:553
void resize(size_type count, const value_type &value) noexcept
Definition vector.hpp:599
iterator end() noexcept
Get an iterator to the end of the data.
Definition vector.hpp:404
typename Allocator::const_pointer const_pointer
Definition vector.hpp:30
reference emplace_back(Args &&...args) noexcept
Definition vector.hpp:573
tenno::size size_type
Definition vector.hpp:26
bool empty() const noexcept
Definition vector.hpp:501
vector & operator=(const vector &other)
Definition vector.hpp:108
void assign(size_type count, const T &value)
Definition vector.hpp:157
expected< tenno::reference_wrapper< const T >, tenno::error > back() const
Definition vector.hpp:286
const value_type & const_reference
Definition vector.hpp:28
vector(const vector &other)
Definition vector.hpp:54
void swap(vector &other) noexcept
Definition vector.hpp:610
vector & operator=(std::initializer_list< value_type > ilist)
Definition vector.hpp:142
reverse_iterator rend() noexcept
Get an reverse_iterator to the end of the data.
Definition vector.hpp:496
vector(size_type count, const T &value, const Allocator &alloc=Allocator())
Definition vector.hpp:37
iterator begin() noexcept
Get an iterator to the beginning of the data.
Definition vector.hpp:389
void assign_range(const tenno::range< T > &r)
Definition vector.hpp:215
tenno::expected< pointer, tenno::error > data() noexcept
Definition vector.hpp:299
vector(std::initializer_list< T > init, const Allocator &alloc=Allocator())
Definition vector.hpp:89
Allocator allocator_type
Definition vector.hpp:25
vector(vector &&other, const Allocator &alloc)
Definition vector.hpp:82
size_t size
Definition types.hpp:13
error
Definition error.hpp:12
constexpr std::remove_reference_t< T > && move(T &&t) noexcept
Move a value from one location to another.
Definition utility.hpp:21
void swap(T &a, T &b) noexcept
Exchanges the values of a and b.
Definition algorithm.hpp:99
An iterator to iterate over the data.
Definition vector.hpp:321
std::forward_iterator_tag iterator_category
Definition vector.hpp:322
tenno::vector< T, Allocator > & vec
Definition vector.hpp:329
iterator(tenno::vector< T, Allocator > &_vec, const tenno::size _index)
Definition vector.hpp:331
iterator & operator++() noexcept
Definition vector.hpp:337
tenno::expected< tenno::reference_wrapper< T >, tenno::error > get() noexcept
Definition vector.hpp:372
tenno::expected< tenno::reference_wrapper< T >, tenno::error > operator->() noexcept
Definition vector.hpp:367
tenno::expected< tenno::reference_wrapper< T >, tenno::error > operator*() noexcept
Definition vector.hpp:361
iterator operator++(T) noexcept
Definition vector.hpp:343
bool operator!=(const iterator &other) const noexcept
Definition vector.hpp:355
std::ptrdiff_t difference_type
Definition vector.hpp:323
bool operator==(const iterator &other) const noexcept
Definition vector.hpp:350
An reverse_iterator to iterate over the data.
Definition vector.hpp:413
tenno::expected< tenno::reference_wrapper< T >, tenno::error > get() noexcept
Definition vector.hpp:464
bool operator!=(const reverse_iterator &other) const noexcept
Definition vector.hpp:447
reverse_iterator operator++(T) noexcept
Definition vector.hpp:435
std::forward_iterator_tag reverse_iterator_category
Definition vector.hpp:414
bool operator==(const reverse_iterator &other) const noexcept
Definition vector.hpp:442
tenno::expected< tenno::reference_wrapper< T >, tenno::error > operator*() noexcept
Definition vector.hpp:453
reverse_iterator(tenno::vector< T, Allocator > &_vec, const long long int _index)
Definition vector.hpp:423
reverse_iterator & operator++() noexcept
Definition vector.hpp:429
tenno::vector< T, Allocator > & vec
Definition vector.hpp:421
tenno::expected< tenno::reference_wrapper< T >, tenno::error > operator->() noexcept
Definition vector.hpp:459