A 2D tile-based sandbox game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SlotVector.h 2.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #pragma once
  2. #include <vector>
  3. #include <type_traits>
  4. namespace Swan {
  5. template<typename T>
  6. struct SlotVectorDefaultSentinel {
  7. static constexpr T sentinel() { return T{}; }
  8. };
  9. template<typename T, T val>
  10. struct SlotVectorValueSentinel {
  11. static constexpr T sentinel() { return val; }
  12. };
  13. template<typename T, typename Sentinel = SlotVectorDefaultSentinel<T>>
  14. class SlotVector {
  15. public:
  16. class Iterator {
  17. public:
  18. Iterator(SlotVector<T, Sentinel> *vec, size_t idx): vec_(vec), idx_(idx) {}
  19. Iterator(const Iterator &) = default;
  20. void seek() {
  21. size_t size = vec_->vec_.size();
  22. while (idx_ < size && (*vec_)[idx_] == Sentinel::sentinel())
  23. idx_ += 1;
  24. }
  25. void operator++() {
  26. idx_ += 1;
  27. seek();
  28. }
  29. T &operator*() {
  30. return (*vec_)[idx_];
  31. }
  32. bool operator==(const Iterator &other) const {
  33. return idx_ == other.idx_;
  34. }
  35. bool operator!=(const Iterator &other) const {
  36. return !(idx_ == other.idx_);
  37. }
  38. size_t operator-(const Iterator &other) const {
  39. return idx_ - other.idx_;
  40. }
  41. private:
  42. SlotVector<T, Sentinel> *vec_;
  43. size_t idx_;
  44. };
  45. T &operator[](size_t idx) { return vec_[idx]; }
  46. T &at(size_t idx) { return vec_.at(idx); }
  47. size_t size() { return vec_.size(); }
  48. bool empty() { return vec_.size() == free_.size(); }
  49. Iterator begin() { Iterator it(this, 0); it.seek(); return it; }
  50. Iterator end() { return Iterator(this, vec_.size()); }
  51. void clear() noexcept { vec_.clear(); free_.clear(); }
  52. void shrink_to_fit() {
  53. vec_.shrink_to_fit();
  54. free_.shrink_to_fit();
  55. }
  56. size_t insert(T val) {
  57. if (free_.size() > 0) {
  58. size_t idx = free_.back();
  59. vec_[idx] = std::move(val);
  60. free_.pop_back();
  61. return idx;
  62. } else {
  63. size_t idx = vec_.size();
  64. vec_.push_back(std::move(val));
  65. return idx;
  66. }
  67. }
  68. template<typename... Args>
  69. size_t emplace(Args&&... args) {
  70. if (free_.size() > 0) {
  71. size_t idx = free_.back();
  72. T *slot = vec_.data() + idx;
  73. slot->~T();
  74. new (slot) T(std::forward<Args>(args)...);
  75. return idx;
  76. } else {
  77. size_t idx = vec_.size();
  78. vec_.emplace_back(std::forward<Args>(args)...);
  79. return idx;
  80. }
  81. }
  82. void erase(size_t idx) {
  83. vec_[idx] = Sentinel::sentinel();
  84. free_.push_back(idx);
  85. }
  86. private:
  87. std::vector<T> vec_;
  88. std::vector<size_t> free_;
  89. };
  90. }