commonlib
vector_with_ids.h
Go to the documentation of this file.
1 
27 #pragma once
28 
29 #include <vector>
30 #include <unordered_map>
31 
32 #include <cassert>
34 
35 BEGIN_NAMESPACE_CONTAINERS
36 
37 template <typename T>
39 {
40 public:
43 
44 public:
45 
56  VectorWithIds(std::size_t idMinGenerated = 0, std::size_t idStepSizeGenerated = 1);
57 
61  VectorWithIds(const VectorWithIds& other);
62 
67 
72 
77 
83  T& operator[](std::size_t pos);
84 
90  const T& operator[](std::size_t pos) const;
91 
96  T& back();
97 
102  const T& back() const;
103 
107  void clear();
108 
112  std::size_t size() const;
113 
117  bool empty() const;
118 
127  void emplaceBack();
128 
137  bool emplaceBackWithId(int32_t id);
138 
144  iterator erase(iterator position);
145 
151  iterator erase(std::size_t pos);
152 
158  void swap(int32_t posA, int32_t posB);
159 
165  int32_t getId(int32_t pos) const;
166 
167 
176  iterator findById(int32_t id);
177 
186  const_iterator findById(int32_t id) const;
187 
198  void cloneStructure(const VectorWithIds<T>& other);
199 
200 
205  {
206  return iterator(pairs.begin());
207  }
208 
213  {
214  return iterator(pairs.end());
215  }
216 
221  {
222  return const_iterator(pairs.begin());
223  }
224 
229  {
230  return const_iterator(pairs.end());
231  }
232 
237  {
238  return begin();
239  }
240 
245  {
246  return end();
247  }
248 
249 private:
250  int32_t idMin, idStep;
251 
252  std::vector<std::pair<int32_t, T>> pairs;
253  std::unordered_map<int32_t, typename std::vector<std::pair<int32_t, T>>::iterator> pairsMap;
254 
255  void rebuildPairMap();
256 };
257 
258 template <class T>
259 VectorWithIds<T>::VectorWithIds(std::size_t idMinGenerated, std::size_t idStepSizeGenerated)
260 {
261  idMin = static_cast<int32_t>(idMinGenerated);
262 
263  assert(idStepSizeGenerated > 0);
264  idStep = static_cast<int32_t>(idStepSizeGenerated);
265 }
266 
267 template <typename T>
269 {
270  idMin = other.idMin;
271  idStep = other.idStep;
272  pairs = other.pairs;
273  rebuildPairMap();
274 }
275 
276 template <typename T>
278 {
279  if (this != &other)
280  {
281  idMin = other.idMin;
282  idStep = other.idStep;
283  pairs = other.pairs;
284  rebuildPairMap();
285  }
286  return *this;
287 }
288 
289 template <typename T>
291 {
292  idMin = other.idMin;
293  idStep = other.idStep;
294 
295  pairs = std::move(other.pairs);
296  rebuildPairMap();
297 
298  other.pairsMap.clear();
299 }
300 
301 template <typename T>
303 {
304  if (this != &other)
305  {
306  idMin = other.idMin;
307  idStep = other.idStep;
308 
309  pairs = std::move(other.pairs);
310  rebuildPairMap();
311 
312  other.pairsMap.clear();
313  }
314  return *this;
315 }
316 
317 template <typename T>
318 T& VectorWithIds<T>::operator[](std::size_t pos)
319 {
320  return pairs[pos].second;
321 }
322 
323 template <typename T>
324 const T& VectorWithIds<T>::operator[](std::size_t pos) const
325 {
326  return pairs[pos].second;
327 }
328 
329 template <typename T>
331 {
332  return pairs.back().second;
333 }
334 
335 template <typename T>
336 const T& VectorWithIds<T>::back() const
337 {
338  return pairs.back().second;
339 }
340 
341 template <typename T>
343 {
344  pairsMap.clear();
345  pairs.clear();
346 }
347 
348 template <typename T>
349 std::size_t VectorWithIds<T>::size() const
350 {
351  return pairs.size();
352 }
353 
354 template <typename T>
356 {
357  return pairs.empty();
358 }
359 
360 template <typename T>
362 {
363  auto it = pairs.erase(position.pointee);
364  rebuildPairMap();
365  return iterator(it);
366 }
367 
368 template <typename T>
370 {
371  auto it = pairs.erase(pairs.begin() + pos);
372  rebuildPairMap();
373  return iterator(it);
374 }
375 
376 template <typename T>
377 void VectorWithIds<T>::swap(int32_t posA, int32_t posB)
378 {
379  if (posA != posB)
380  {
381  std::swap(pairs[posA], pairs[posB]);
382  rebuildPairMap();
383  }
384 }
385 
386 template <typename T>
388 {
389  if (pairs.empty())
390  {
391  // Fill the first index if size is zero
392  pairs.emplace_back();
393  pairs[0].first = idMin;
394  }
395  else
396  {
397  // Find a slot
398  bool slotFound = false;
399  int32_t slotId = idMin;
400 
401  while (!slotFound)
402  {
403  if (pairsMap.find(slotId) == pairsMap.end())
404  {
405  slotFound = true;
406  }
407  else
408  {
409  slotId += idStep;
410  }
411  }
412 
413  // Insert with free slot
414  pairs.emplace_back();
415  (pairs.back()).first = slotId;
416  }
417 
418  rebuildPairMap();
419 }
420 
421 template <typename T>
423 {
424  if (pairsMap.find(id) == pairsMap.end())
425  {
426  pairs.emplace_back();
427  (pairs.back()).first = id;
428  rebuildPairMap();
429  return true;
430  }
431  return false;
432 }
433 
434 template <typename T>
435 int32_t VectorWithIds<T>::getId(int32_t pos) const
436 {
437  return pairs[pos].first;
438 }
439 
440 template <typename T>
442 {
443  auto pairsMapIter = pairsMap.find(id);
444 
445  if (pairsMapIter != pairsMap.end())
446  {
447  return iterator(pairsMapIter->second);
448  }
449  return end();
450 }
451 
452 template <typename T>
454 {
455  auto pairsMapIter = pairsMap.find(id);
456 
457  if (pairsMapIter != pairsMap.end())
458  {
459  return const_iterator(pairsMapIter->second);
460  }
461  else
462  {
463  return end();
464  }
465 }
466 
467 template <typename T>
469 {
470  // Go thorugh
471  const int32_t otherSize = static_cast<int32_t>(other.size());
472  for (int32_t otherPos = 0; otherPos < otherSize; ++otherPos)
473  {
474  // Find the same ID in this vector
475  int32_t otherId = other.getId(otherPos);
476 
477  auto pairsMapIter = pairsMap.find(otherId);
478 
479  if (pairsMapIter != pairsMap.end())
480  {
481  // Reposition
482  const auto thisPos = static_cast<int32_t>(std::distance(pairs.begin(), pairsMapIter->second));
483  swap(thisPos, otherPos);
484  }
485  else
486  {
487  // Create and reposition
488  emplaceBackWithId(otherId);
489  swap(otherPos, int32_t(pairs.size()) - 1);
490  }
491  }
492 
493  // Delete what is redundant
494  if (pairs.size() != other.size())
495  {
496  pairs.resize(other.size());
497  rebuildPairMap();
498  }
499 }
500 
501 template <typename T>
503 {
504  pairsMap.clear();
505  for (auto pairIter = pairs.begin(); pairIter != pairs.end(); ++pairIter)
506  {
507  pairsMap.insert(std::make_pair(pairIter->first, pairIter));
508  }
509 }
510 
511 END_NAMESPACE_CONTAINERS
iterator begin()
Definition: vector_with_ids.h:204
void clear()
Deletes all objects in the container and sets the size to zero.
Definition: vector_with_ids.h:342
iterator erase(iterator position)
Erases an element at an iterator position.
Definition: vector_with_ids.h:361
Definition: vector_with_ids.h:38
VectorWithIds< T > & operator=(const VectorWithIds &other)
Copy assignment.
Definition: vector_with_ids.h:277
T & back()
Mutable access to the last element in the container.
Definition: vector_with_ids.h:330
Definition: vector_with_ids_iterator.h:60
const_iterator cbegin() const
Definition: vector_with_ids.h:236
iterator findById(int32_t id)
Searches for an element with an id passed.
Definition: vector_with_ids.h:441
void swap(int32_t posA, int32_t posB)
Swaps elements in container at indexed positions passed.
Definition: vector_with_ids.h:377
iterator end()
Definition: vector_with_ids.h:212
const_iterator cend() const
Definition: vector_with_ids.h:244
const_iterator begin() const
Definition: vector_with_ids.h:220
const_iterator end() const
Definition: vector_with_ids.h:228
T & operator[](std::size_t pos)
Mutable access element at position.
Definition: vector_with_ids.h:318
std::size_t size() const
Definition: vector_with_ids.h:349
VectorWithIdsIterator provides access to VectorWithIds elements and it&#39;s id numbers.
void emplaceBack()
Constructs an additional element at the at the back of the container by calling a default constructor...
Definition: vector_with_ids.h:387
VectorWithIds(std::size_t idMinGenerated=0, std::size_t idStepSizeGenerated=1)
Constructor with optional minimum automatic id and step between generated ids.
Definition: vector_with_ids.h:259
int32_t getId(int32_t pos) const
Swaps elements in container at indexed positions passed.
Definition: vector_with_ids.h:435
bool emplaceBackWithId(int32_t id)
Constructs an additional element at the at the back of the container by calling a default constructor...
Definition: vector_with_ids.h:422
void cloneStructure(const VectorWithIds< T > &other)
Clones the structure of the container to the one of the passed object.
Definition: vector_with_ids.h:468
bool empty() const
Definition: vector_with_ids.h:355