NoShrinkVector.h
Go to the documentation of this file.
1#ifndef MiscLib__NOSHRINKVECTOR_HEADER__
2#define MiscLib__NOSHRINKVECTOR_HEADER__
4
5namespace MiscLib
6{
7 // This is a special implementation of std::vector. You should be able to use it whereever you could you use std::vector.
8 // For some reason it is faster than the actual std::vector (at least under windows and with the Intel Compiler)
9 // It also has the special property that it never (!!!) frees memory automatically, even if you call clear()
10 // The only way to get rid of the allocated mem is to call ClearTotal() (or during destruction of course)
11 // Note that element constructors and destructors are invoked correctly though, e.g. when calling clear
12 // all elements are destructed.
13 // The advantage is however that no copying takes place for resize operations (unless new memory must be allocated)
14 // So if you have an array whose size constantly varies between 0 and a max size this class is a good choice
15 // SO BE CAREFUL WHEN USING THIS CLASS, IT MAY WASTE A LOT OF MEMORY!
16 template <class T, class AllocatorT = MiscLib::AlignedAllocator<T>>
17 class NoShrinkVector : protected AllocatorT
18 {
19 public:
20 typedef size_t size_type;
21 typedef T value_type;
22 typedef T* iterator;
23 typedef const T* const_iterator;
24 typedef T& reference;
25 typedef const T& const_reference;
26 typedef T* pointer;
27 typedef const T* const_pointer;
28 typedef size_t ptrdiff_t;
29 typedef std::reverse_iterator<T*> reverse_iterator;
30 typedef std::reverse_iterator<const T*> const_reverse_iterator;
31
33 {
34 m_begin = NULL;
35 m_end = NULL;
36 m_capacity = NULL;
37 }
38
40 {
41 m_begin = AllocatorT::allocate(s);
42 m_end = m_begin + s;
43 m_capacity = m_end;
44 value_type v;
45 for (size_type i = 0; i < s; ++i)
46 {
47 AllocatorT::construct(m_begin + i, v);
48 }
49 }
50
52 {
53 m_begin = AllocatorT::allocate(s);
54 m_end = m_begin + s;
55 m_capacity = m_end;
56 for (size_type i = 0; i < s; ++i)
57 {
58 AllocatorT::construct(m_begin + i, v);
59 }
60 }
61
63 {
64 size_type s = v.size();
65 if (!s)
66 {
67 m_begin = NULL;
68 m_end = NULL;
69 m_capacity = NULL;
70 return;
71 }
72 m_begin = AllocatorT::allocate(s);
73 m_end = m_begin + s;
74 m_capacity = m_end;
75 for (size_type i = 0; i < s; ++i)
76 {
77 AllocatorT::construct(m_begin + i, v.m_begin[i]);
78 }
79 }
80
81 template <class OtherAllocatorT>
83 {
84 size_type s = v.size();
85 if (!s)
86 {
87 m_begin = NULL;
88 m_end = NULL;
89 m_capacity = NULL;
90 return;
91 }
92 m_begin = AllocatorT::allocate(s);
93 m_end = m_begin + s;
94 m_capacity = m_end;
95 for (size_type i = 0; i < s; ++i)
96 {
97 AllocatorT::construct(m_begin + i, v.m_begin[i]);
98 }
99 }
100
102 {
103 if (m_begin)
104 {
105 for (size_type i = 0; i < size(); ++i)
106 {
107 AllocatorT::destroy(m_begin + i);
108 }
109 AllocatorT::deallocate(m_begin, capacity());
110 }
111 }
112
115 {
116 if (&v == this)
117 {
118 return *this;
119 }
120 size_type s = v.size();
121 if (!s)
122 {
123 clear();
124 return *this;
125 }
126 if (m_begin)
127 {
128 for (size_type i = 0; i < size(); ++i)
129 {
130 AllocatorT::destroy(m_begin + i);
131 }
132 AllocatorT::deallocate(m_begin, capacity());
133 }
134 m_begin = AllocatorT::allocate(s);
135 m_end = m_begin + s;
136 m_capacity = m_end;
137 for (size_type i = 0; i < s; ++i)
138 {
139 AllocatorT::construct(m_begin + i, v.m_begin[i]);
140 }
141 return *this;
142 }
143
144 template <class OtherAllocatorT>
147 {
148 size_type s = v.size();
149 if (!s)
150 {
151 clear();
152 return *this;
153 }
154 if (m_begin)
155 {
156 for (size_type i = 0; i < size(); ++i)
157 {
158 AllocatorT::destroy(m_begin + i);
159 }
160 AllocatorT::deallocate(m_begin, capacity());
161 }
162 m_begin = AllocatorT::allocate(s);
163 m_end = m_begin + s;
164 m_capacity = m_end;
165 for (size_type i = 0; i < s; ++i)
166 {
167 AllocatorT::construct(m_begin + i, v.m_begin[i]);
168 }
169 return *this;
170 }
171
172 void
174 {
175 for (size_type i = 0; i < size(); ++i)
176 {
177 AllocatorT::destroy(m_begin + i);
178 }
179 m_end = m_begin;
180 }
181
182 void
184 {
185 if (m_begin)
186 {
187 for (size_type i = 0; i < size(); ++i)
188 {
189 AllocatorT::destroy(m_begin + i);
190 }
191 AllocatorT::deallocate(m_begin, capacity());
192 }
193 m_end = m_begin = m_capacity = NULL;
194 }
195
196 void
198 {
199 if (!s)
200 {
201 return;
202 }
203 if (capacity() < s)
204 {
205 size_type olds = size();
206 T* newBegin = AllocatorT::allocate(s);
207 if (m_begin)
208 {
209 for (size_type i = 0; i < olds; ++i)
210 {
211 AllocatorT::construct(newBegin + i, m_begin[i]);
212 AllocatorT::destroy(m_begin + i);
213 }
214 AllocatorT::deallocate(m_begin, capacity());
215 }
216 m_end = newBegin + olds;
217 m_begin = newBegin;
218 m_capacity = m_begin + s;
219 }
220 }
221
223 size() const
224 {
225 return m_end - m_begin;
226 }
227
229 capacity() const
230 {
231 return m_capacity - m_begin;
232 }
233
234 void
236 {
237 if (!s)
238 {
239 clear();
240 return;
241 }
242 if (capacity() >= s)
243 {
244 for (size_type i = s; i < size(); ++i)
245 {
246 AllocatorT::destroy(m_begin + i);
247 }
248 for (size_type i = size(); i < s; ++i)
249 {
250 AllocatorT::construct(m_begin + i, v);
251 }
252 m_end = m_begin + s;
253 return;
254 }
255 T* newBegin = AllocatorT::allocate(2 * s);
256 if (m_begin)
257 {
258 for (size_type i = 0; i < size(); ++i)
259 {
260 AllocatorT::construct(newBegin + i, m_begin[i]);
261 AllocatorT::destroy(m_begin + i);
262 }
263 AllocatorT::deallocate(m_begin, capacity());
264 for (size_type i = size(); i < s; ++i)
265 {
266 AllocatorT::construct(newBegin + i, v);
267 }
268 }
269 else
270 {
271 for (size_type i = 0; i < s; ++i)
272 {
273 AllocatorT::construct(newBegin + i, v);
274 }
275 }
276 m_end = newBegin + s;
277 m_begin = newBegin;
278 m_capacity = m_begin + 2 * s;
279 }
280
281 void
283 {
284 resize(s, value_type());
285 }
286
287 operator T*()
288 {
289 return m_begin;
290 }
291
292 operator const T*() const
293 {
294 return m_begin;
295 }
296
297 T&
299 {
300 return m_begin[i];
301 }
302
303 const T&
304 at(size_type i) const
305 {
306 return m_begin[i];
307 }
308
309 void
310 push_back(const T& v)
311 {
312 if (m_end >= m_capacity)
313 {
314 size_type olds = size();
315 size_type s = olds * 2;
316 if (!s)
317 {
318 s = 1;
319 }
320 T* newBegin = AllocatorT::allocate(s);
321 if (m_begin)
322 {
323 for (size_type i = 0; i < olds; ++i)
324 {
325 AllocatorT::construct(newBegin + i, m_begin[i]);
326 AllocatorT::destroy(m_begin + i);
327 }
328 AllocatorT::deallocate(m_begin, capacity());
329 }
330 m_end = newBegin + olds;
331 m_begin = newBegin;
332 m_capacity = m_begin + s;
333 }
334 AllocatorT::construct(m_end, v);
335 ++m_end;
336 }
337
338 void
339 insert(T* where, const T& v)
340 {
341 size_type whereIdx = where - m_begin;
342 if (m_end >= m_capacity)
343 {
344 size_type olds = size();
345 size_type s = olds * 2;
346 if (!s)
347 {
348 s = 1;
349 }
350 T* newBegin = AllocatorT::allocate(s);
351 if (m_begin)
352 {
353 for (size_type i = 0; i < olds; ++i)
354 {
355 AllocatorT::construct(newBegin + i, m_begin[i]);
356 AllocatorT::destroy(m_begin + i);
357 }
358 AllocatorT::deallocate(m_begin, capacity());
359 }
360 m_end = newBegin + olds;
361 m_begin = newBegin;
362 m_capacity = m_begin + s;
363 where = m_begin + whereIdx;
364 }
365 if (size() > whereIdx)
366 {
367 AllocatorT::construct(m_end, m_begin[size() - 1]);
368 for (size_type i = size() - 1; i > whereIdx; --i)
369 {
370 m_begin[i] = m_begin[i - 1];
371 }
372 *where = v;
373 }
374 else
375 {
376 AllocatorT::construct(where, v);
377 }
378 ++m_end;
379 }
380
381 void
382 erase(T* where)
383 {
384 for (size_type i = where - m_begin; i < size() - 1; ++i)
385 {
386 m_begin[i] = m_begin[i + 1];
387 }
388 --m_end;
389 AllocatorT::destroy(m_end);
390 }
391
392 void
394 {
395 --m_end;
396 AllocatorT::destroy(m_end);
397 }
398
399 T*
401 {
402 return m_begin;
403 }
404
405 const T*
406 begin() const
407 {
408 return m_begin;
409 }
410
411 T*
413 {
414 return m_end;
415 }
416
417 const T*
418 end() const
419 {
420 return m_end;
421 }
422
425 {
426 return std::reverse_iterator<T*>(m_end);
427 }
428
430 rbegin() const
431 {
432 return std::reverse_iterator<const T*>(m_end);
433 }
434
437 {
438 return std::reverse_iterator<T*>(m_begin);
439 }
440
442 rend() const
443 {
444 return std::reverse_iterator<const T*>(m_begin);
445 }
446
447 T&
449 {
450 return *(m_end - 1);
451 }
452
453 const T&
454 back() const
455 {
456 return *(m_end - 1);
457 }
458
459 T&
461 {
462 return *m_begin;
463 }
464
465 const T&
466 front() const
467 {
468 return *m_begin;
469 }
470
471 private:
472 T* m_begin;
473 T* m_end;
474 T* m_capacity;
475 };
476}; // namespace MiscLib
477
478#endif
const_reverse_iterator rend() const
void resize(size_type s, const value_type &v)
const T * end() const
void resize(size_type s)
std::reverse_iterator< const T * > const_reverse_iterator
NoShrinkVector(const NoShrinkVector< T, OtherAllocatorT > &v)
NoShrinkVector< T > & operator=(const NoShrinkVector< T, AllocatorT > &v)
const T & front() const
NoShrinkVector(size_type s, const T &v)
std::reverse_iterator< T * > reverse_iterator
size_type size() const
reverse_iterator rend()
NoShrinkVector(const NoShrinkVector< T, AllocatorT > &v)
NoShrinkVector< T > & operator=(const NoShrinkVector< T, OtherAllocatorT > &v)
const T & back() const
void push_back(const T &v)
void reserve(size_type s)
reverse_iterator rbegin()
size_type capacity() const
const T & at(size_type i) const
const_reverse_iterator rbegin() const
const T * begin() const
void insert(T *where, const T &v)