|
2 | 2 |
|
3 | 3 | #include <Arduino.h> |
4 | 4 |
|
| 5 | + |
| 6 | +template <class T> |
| 7 | +void swap_(T& a, T& b) noexcept { |
| 8 | + T tmp {a}; |
| 9 | + a = b; |
| 10 | + b = tmp; |
| 11 | +} |
| 12 | + |
| 13 | + |
5 | 14 | /*! |
6 | 15 | * Generic Vector. |
7 | 16 | */ |
8 | 17 | template <class T> |
9 | 18 | class Vector { |
10 | 19 | public: |
11 | | - Vector() {} |
| 20 | + Vector() = default; |
| 21 | + Vector(Vector const& v); |
12 | 22 |
|
13 | 23 | /*! Create a Vector with `size` elements. |
14 | 24 | * |
15 | | - * \param size Size of the Vector. |
| 25 | + * \param size Vector size. |
16 | 26 | */ |
17 | 27 | Vector(size_t const); |
18 | 28 |
|
19 | 29 | /*! |
20 | 30 | * Create a Vector with `size` elements from a C array. |
21 | 31 | * |
22 | | - * \param size Size of the Vector. |
23 | | - * \param data Pointer to data. |
| 32 | + * \param data C array. |
24 | 33 | */ |
25 | | - Vector(size_t const, T* const); |
| 34 | + template <size_t n> |
| 35 | + Vector(T const (&)[n]); |
26 | 36 |
|
27 | | - Vector(Vector const& v); |
| 37 | + /*! |
| 38 | + * Create a Vector with `size` elements from a block of raw memory. |
| 39 | + * |
| 40 | + * \param data Pointer to data, Vector takes ownership. |
| 41 | + * \param size Vector size. |
| 42 | + */ |
| 43 | + Vector(T* const, size_t const); |
28 | 44 |
|
29 | 45 | ~Vector(); |
30 | 46 |
|
31 | 47 | Vector& operator=(Vector); |
| 48 | + T& operator[](size_t const); |
| 49 | + T const& operator [](size_t const) const; |
32 | 50 |
|
| 51 | + T* begin(); |
| 52 | + T* end(); |
| 53 | + T const* begin() const; |
| 54 | + T const* end() const; |
33 | 55 |
|
34 | 56 | /*! |
35 | | - * Get a reference to an element. |
| 57 | + * Get the underlying data. |
36 | 58 | * |
37 | | - * This can be used for both retrieval as well as assignment. |
| 59 | + * \return data. |
| 60 | + */ |
| 61 | + T* data() const; |
| 62 | + |
| 63 | + /*! |
| 64 | + * Get the number of elements. |
38 | 65 | * |
39 | | - * \param index Index. |
| 66 | + * \return Vector size. |
| 67 | + */ |
| 68 | + size_t size() const; |
| 69 | + |
| 70 | + /*! |
| 71 | + * Set the number of elements. |
40 | 72 | * |
41 | | - * \return Reference to element at index `index`. |
| 73 | + * \param size Vector size. |
42 | 74 | */ |
43 | | - T& operator[](size_t) const; |
| 75 | + void resize(size_t const); |
| 76 | + |
| 77 | + /*! Clear the contents. */ |
| 78 | + void clear(); |
44 | 79 |
|
45 | | - size_t size() const { |
46 | | - return size_; |
47 | | - } |
48 | 80 | /*! |
49 | | - * Resize the Vector. |
| 81 | + * Add an element to the back. |
50 | 82 | * |
51 | | - * \param size New size of the Vector. |
| 83 | + * \param el Element. |
52 | 84 | */ |
53 | | - void resize(size_t); |
| 85 | + void push_back(T const&); |
| 86 | + |
| 87 | + /*! |
| 88 | + * Remove an element from the back. |
| 89 | + * |
| 90 | + * \return Element. |
| 91 | + */ |
| 92 | + T pop_back(); |
54 | 93 |
|
55 | 94 | template <class U> |
56 | 95 | friend void swap(Vector<U>&, Vector<U>&) noexcept; |
57 | 96 |
|
58 | | - //T* begin(); |
59 | | - //T* end(); |
60 | | - //T const* begin() const; |
61 | | - //T const* end() const; |
62 | | - |
63 | 97 | private: |
| 98 | + void copy_(T const* const); |
| 99 | + |
64 | 100 | size_t size_ {0}; |
65 | 101 | T* data_ {nullptr}; |
66 | 102 | }; |
67 | 103 |
|
| 104 | + |
68 | 105 | template <class T> |
69 | | -void swap_(T& a, T& b) noexcept { |
70 | | - T tmp {a}; |
71 | | - a = b; |
72 | | - b = tmp; |
| 106 | +Vector<T>::Vector(Vector const& other) |
| 107 | + : size_ {other.size_}, data_ {new T[other.size_]} { |
| 108 | + copy_(other.data_); |
73 | 109 | } |
74 | 110 |
|
75 | | -template <class U> |
76 | | -void swap(Vector<U>& a, Vector<U>& b) noexcept { |
77 | | - swap_(a.size_, b.size_); |
78 | | - swap_(a.data_, b.data_); |
| 111 | +template <class T> |
| 112 | +Vector<T>::Vector(size_t const size) |
| 113 | + : size_ {size}, data_ {new T[size]} {} |
| 114 | + |
| 115 | +template <class T> |
| 116 | +Vector<T>::Vector(T* const data, size_t const size) |
| 117 | + : size_ {size}, data_ {data} {} |
| 118 | + |
| 119 | +template <class T> |
| 120 | +template <size_t n> |
| 121 | +Vector<T>::Vector(T const (&data)[n]) |
| 122 | + : size_ {n}, data_ {new T[n]} { |
| 123 | + copy_(data); |
| 124 | +} |
| 125 | + |
| 126 | +template <class T> |
| 127 | +Vector<T>::~Vector() { |
| 128 | + delete[] data_; |
79 | 129 | } |
80 | 130 |
|
81 | 131 |
|
82 | 132 | template <class T> |
83 | | -Vector<T>::Vector(size_t const size) { |
84 | | - resize(size); |
| 133 | +Vector<T>& Vector<T>::operator=(Vector<T> other) { |
| 134 | + swap(*this, other); |
| 135 | + return *this; |
85 | 136 | } |
86 | 137 |
|
87 | 138 | template <class T> |
88 | | -Vector<T>::Vector(size_t const size, T* const data) { |
89 | | - this->size_ = size; |
90 | | - data_ = data; |
| 139 | +T& Vector<T>::operator[](size_t const idx) { |
| 140 | + return data_[idx]; |
91 | 141 | } |
92 | 142 |
|
93 | 143 | template <class T> |
94 | | -Vector<T>::Vector(Vector const& v) : size_ {v.size_} { |
95 | | - data_ = new T[size_]; |
96 | | - for (size_t i {0}; i < size_; i++) { |
97 | | - data_[i] = v.data_[i]; |
98 | | - } |
| 144 | +T const& Vector<T>::operator[](size_t const idx) const { |
| 145 | + return data_[idx]; |
99 | 146 | } |
100 | 147 |
|
| 148 | + |
101 | 149 | template <class T> |
102 | | -Vector<T>::~Vector() { |
103 | | - delete[] data_; |
| 150 | +T* Vector<T>::begin() { |
| 151 | + return data_; |
104 | 152 | } |
105 | 153 |
|
106 | 154 | template <class T> |
107 | | -Vector<T>& Vector<T>::operator=(Vector v) { |
108 | | - swap(*this, v); |
109 | | - return *this; |
| 155 | +T* Vector<T>::end() { |
| 156 | + return data_ + size_; |
| 157 | +} |
| 158 | + |
| 159 | +template <class T> |
| 160 | +T const* Vector<T>::begin() const { |
| 161 | + return data_; |
| 162 | +} |
| 163 | + |
| 164 | +template <class T> |
| 165 | +T const* Vector<T>::end() const { |
| 166 | + return data_ + size_; |
110 | 167 | } |
111 | 168 |
|
112 | 169 |
|
113 | 170 | template <class T> |
114 | | -T& Vector<T>::operator[](size_t const index) const { |
115 | | - return data_[index]; |
| 171 | +T* Vector<T>::data() const { |
| 172 | + return data_; |
| 173 | +} |
| 174 | + |
| 175 | +template <class T> |
| 176 | +size_t Vector<T>::size() const { |
| 177 | + return size_; |
116 | 178 | } |
117 | 179 |
|
118 | 180 | template <class T> |
119 | 181 | void Vector<T>::resize(size_t const size) { |
120 | | - T* newData {new T[size]}; |
121 | | - for (size_t i {0}; i < min(this->size_, size); i++) { |
122 | | - newData[i] = data_[i]; |
123 | | - } |
| 182 | + size_ = min(size_, size); |
| 183 | + |
| 184 | + T* data {new T[size]}; |
| 185 | + swap_(data_, data); |
| 186 | + copy_(data); |
| 187 | + delete[] data; |
| 188 | + |
| 189 | + size_ = size; |
| 190 | +} |
| 191 | + |
| 192 | +template <class T> |
| 193 | +void Vector<T>::clear() { |
| 194 | + size_ = 0; |
124 | 195 | delete[] data_; |
125 | | - data_ = newData; |
| 196 | + data_ = nullptr; |
| 197 | +} |
| 198 | + |
| 199 | +template <class T> |
| 200 | +void Vector<T>::push_back(T const& el) { |
| 201 | + resize(++size_); |
| 202 | + data_[size_ - 1] = el; |
| 203 | +} |
| 204 | + |
| 205 | +template <class T> |
| 206 | +T Vector<T>::pop_back() { |
| 207 | + T el {data_[size_ - 1]}; |
| 208 | + resize(--size_); |
| 209 | + return el; |
| 210 | +} |
126 | 211 |
|
127 | | - this->size_ = size; |
| 212 | + |
| 213 | +template <class T> |
| 214 | +void Vector<T>::copy_(T const* const data) { |
| 215 | + for (size_t i {0}; i < size_; ++i) { |
| 216 | + data_[i] = data[i]; |
| 217 | + } |
| 218 | +} |
| 219 | + |
| 220 | + |
| 221 | +template <class U> |
| 222 | +void swap(Vector<U>& a, Vector<U>& b) noexcept { |
| 223 | + swap_(a.size_, b.size_); |
| 224 | + swap_(a.data_, b.data_); |
128 | 225 | } |
0 commit comments