EnTT  3.5.0
storage.hpp
1 #ifndef ENTT_ENTITY_STORAGE_HPP
2 #define ENTT_ENTITY_STORAGE_HPP
3 
4 
5 #include <algorithm>
6 #include <iterator>
7 #include <utility>
8 #include <vector>
9 #include <cstddef>
10 #include <type_traits>
11 #include "../config/config.h"
12 #include "../core/algorithm.hpp"
13 #include "../core/type_traits.hpp"
14 #include "entity.hpp"
15 #include "sparse_set.hpp"
16 
17 
18 namespace entt {
19 
20 
48 template<typename Entity, typename Type, typename = std::void_t<>>
49 class storage: public sparse_set<Entity> {
50  static_assert(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>, "The managed type must be at least move constructible and assignable");
51 
54 
55  template<bool Const>
56  class storage_iterator final {
57  friend class storage<Entity, Type>;
58 
59  using instance_type = std::conditional_t<Const, const std::vector<Type>, std::vector<Type>>;
60  using index_type = typename traits_type::difference_type;
61 
62  storage_iterator(instance_type &ref, const index_type idx) ENTT_NOEXCEPT
63  : instances{&ref}, index{idx}
64  {}
65 
66  public:
67  using difference_type = index_type;
68  using value_type = Type;
69  using pointer = std::conditional_t<Const, const value_type *, value_type *>;
70  using reference = std::conditional_t<Const, const value_type &, value_type &>;
71  using iterator_category = std::random_access_iterator_tag;
72 
73  storage_iterator() ENTT_NOEXCEPT = default;
74 
75  storage_iterator & operator++() ENTT_NOEXCEPT {
76  return --index, *this;
77  }
78 
79  storage_iterator operator++(int) ENTT_NOEXCEPT {
80  storage_iterator orig = *this;
81  return ++(*this), orig;
82  }
83 
84  storage_iterator & operator--() ENTT_NOEXCEPT {
85  return ++index, *this;
86  }
87 
88  storage_iterator operator--(int) ENTT_NOEXCEPT {
89  storage_iterator orig = *this;
90  return operator--(), orig;
91  }
92 
93  storage_iterator & operator+=(const difference_type value) ENTT_NOEXCEPT {
94  index -= value;
95  return *this;
96  }
97 
98  storage_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
99  storage_iterator copy = *this;
100  return (copy += value);
101  }
102 
103  storage_iterator & operator-=(const difference_type value) ENTT_NOEXCEPT {
104  return (*this += -value);
105  }
106 
107  storage_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
108  return (*this + -value);
109  }
110 
111  difference_type operator-(const storage_iterator &other) const ENTT_NOEXCEPT {
112  return other.index - index;
113  }
114 
115  [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
116  const auto pos = size_type(index-value-1);
117  return (*instances)[pos];
118  }
119 
120  [[nodiscard]] bool operator==(const storage_iterator &other) const ENTT_NOEXCEPT {
121  return other.index == index;
122  }
123 
124  [[nodiscard]] bool operator!=(const storage_iterator &other) const ENTT_NOEXCEPT {
125  return !(*this == other);
126  }
127 
128  [[nodiscard]] bool operator<(const storage_iterator &other) const ENTT_NOEXCEPT {
129  return index > other.index;
130  }
131 
132  [[nodiscard]] bool operator>(const storage_iterator &other) const ENTT_NOEXCEPT {
133  return index < other.index;
134  }
135 
136  [[nodiscard]] bool operator<=(const storage_iterator &other) const ENTT_NOEXCEPT {
137  return !(*this > other);
138  }
139 
140  [[nodiscard]] bool operator>=(const storage_iterator &other) const ENTT_NOEXCEPT {
141  return !(*this < other);
142  }
143 
144  [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
145  const auto pos = size_type(index-1u);
146  return &(*instances)[pos];
147  }
148 
149  [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
150  return *operator->();
151  }
152 
153  private:
154  instance_type *instances;
155  index_type index;
156  };
157 
158 public:
160  using object_type = Type;
162  using entity_type = Entity;
164  using size_type = std::size_t;
166  using iterator = storage_iterator<false>;
168  using const_iterator = storage_iterator<true>;
170  using reverse_iterator = Type *;
172  using const_reverse_iterator = const Type *;
173 
174 
183  void reserve(const size_type cap) {
185  instances.reserve(cap);
186  }
187 
189  void shrink_to_fit() {
191  instances.shrink_to_fit();
192  }
193 
206  [[nodiscard]] const object_type * raw() const ENTT_NOEXCEPT {
207  return instances.data();
208  }
209 
211  [[nodiscard]] object_type * raw() ENTT_NOEXCEPT {
212  return const_cast<object_type *>(std::as_const(*this).raw());
213  }
214 
223  [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT {
224  const typename traits_type::difference_type pos = underlying_type::size();
225  return const_iterator{instances, pos};
226  }
227 
229  [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
230  return cbegin();
231  }
232 
234  [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
235  const typename traits_type::difference_type pos = underlying_type::size();
236  return iterator{instances, pos};
237  }
238 
249  [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
250  return const_iterator{instances, {}};
251  }
252 
254  [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
255  return cend();
256  }
257 
259  [[nodiscard]] iterator end() ENTT_NOEXCEPT {
260  return iterator{instances, {}};
261  }
262 
272  [[nodiscard]] const_reverse_iterator crbegin() const ENTT_NOEXCEPT {
273  return instances.data();
274  }
275 
277  [[nodiscard]] const_reverse_iterator rbegin() const ENTT_NOEXCEPT {
278  return crbegin();
279  }
280 
282  [[nodiscard]] reverse_iterator rbegin() ENTT_NOEXCEPT {
283  return instances.data();
284  }
285 
296  [[nodiscard]] const_reverse_iterator crend() const ENTT_NOEXCEPT {
297  return crbegin() + instances.size();
298  }
299 
301  [[nodiscard]] const_reverse_iterator rend() const ENTT_NOEXCEPT {
302  return crend();
303  }
304 
306  [[nodiscard]] reverse_iterator rend() ENTT_NOEXCEPT {
307  return rbegin() + instances.size();
308  }
309 
322  [[nodiscard]] const object_type & get(const entity_type entt) const {
323  return instances[underlying_type::index(entt)];
324  }
325 
327  [[nodiscard]] object_type & get(const entity_type entt) {
328  return const_cast<object_type &>(std::as_const(*this).get(entt));
329  }
330 
336  [[nodiscard]] const object_type * try_get(const entity_type entt) const {
337  return underlying_type::contains(entt) ? (instances.data() + underlying_type::index(entt)) : nullptr;
338  }
339 
341  [[nodiscard]] object_type * try_get(const entity_type entt) {
342  return const_cast<object_type *>(std::as_const(*this).try_get(entt));
343  }
344 
362  template<typename... Args>
363  void emplace(const entity_type entt, Args &&... args) {
364  if constexpr(std::is_aggregate_v<object_type>) {
365  instances.push_back(Type{std::forward<Args>(args)...});
366  } else {
367  instances.emplace_back(std::forward<Args>(args)...);
368  }
369 
370  // entity goes after component in case constructor throws
372  }
373 
389  template<typename It>
390  void insert(It first, It last, const object_type &value = {}) {
391  instances.insert(instances.end(), std::distance(first, last), value);
392  // entities go after components in case constructors throw
393  underlying_type::insert(first, last);
394  }
395 
409  template<typename EIt, typename CIt>
410  void insert(EIt first, EIt last, CIt from, CIt to) {
411  instances.insert(instances.end(), from, to);
412  // entities go after components in case constructors throw
413  underlying_type::insert(first, last);
414  }
415 
427  void erase(const entity_type entt) {
428  auto other = std::move(instances.back());
429  instances[underlying_type::index(entt)] = std::move(other);
430  instances.pop_back();
432  }
433 
446  void swap(const entity_type lhs, const entity_type rhs) override {
447  std::swap(instances[underlying_type::index(lhs)], instances[underlying_type::index(rhs)]);
448  underlying_type::swap(lhs, rhs);
449  }
450 
491  template<typename Compare, typename Sort = std_sort, typename... Args>
492  void sort(iterator first, iterator last, Compare compare, Sort algo = Sort{}, Args &&... args) {
493  ENTT_ASSERT(!(last < first));
494  ENTT_ASSERT(!(last > end()));
495 
496  const auto from = underlying_type::begin() + std::distance(begin(), first);
497  const auto to = from + std::distance(first, last);
498 
499  const auto apply = [this](const auto lhs, const auto rhs) {
500  std::swap(instances[underlying_type::index(lhs)], instances[underlying_type::index(rhs)]);
501  };
502 
503  if constexpr(std::is_invocable_v<Compare, const object_type &, const object_type &>) {
504  underlying_type::arrange(from, to, std::move(apply), [this, compare = std::move(compare)](const auto lhs, const auto rhs) {
505  return compare(std::as_const(instances[underlying_type::index(lhs)]), std::as_const(instances[underlying_type::index(rhs)]));
506  }, std::move(algo), std::forward<Args>(args)...);
507  } else {
508  underlying_type::arrange(from, to, std::move(apply), std::move(compare), std::move(algo), std::forward<Args>(args)...);
509  }
510  }
511 
513  void clear() {
515  instances.clear();
516  }
517 
518 private:
519  std::vector<object_type> instances;
520 };
521 
522 
524 template<typename Entity, typename Type>
525 class storage<Entity, Type, std::enable_if_t<is_eto_eligible_v<Type>>>: public sparse_set<Entity> {
527 
528 public:
530  using object_type = Type;
532  using entity_type = Entity;
534  using size_type = std::size_t;
535 
549  template<typename... Args>
550  void emplace(const entity_type entt, Args &&... args) {
551  [[maybe_unused]] object_type instance{std::forward<Args>(args)...};
553  }
554 
568  template<typename It>
569  void insert(It first, It last, const object_type & = {}) {
570  underlying_type::insert(first, last);
571  }
572 };
573 
574 
575 }
576 
577 
578 #endif
entt::sparse_set::swap
virtual void swap(const entity_type lhs, const entity_type rhs)
Swaps two entities in the internal packed array.
Definition: sparse_set.hpp:454
entt::storage::crbegin
const_reverse_iterator crbegin() const noexcept
Returns a reverse iterator to the beginning.
Definition: storage.hpp:272
entt::storage::clear
void clear()
Clears a storage.
Definition: storage.hpp:513
entt::sparse_set
Basic sparse set implementation.
Definition: sparse_set.hpp:43
entt::storage::begin
iterator begin() noexcept
Returns an iterator to the beginning.
Definition: storage.hpp:234
entt::storage< Entity, Type, std::enable_if_t< is_eto_eligible_v< Type > > >::object_type
Type object_type
Type of the objects associated with the entities.
Definition: storage.hpp:530
entt::storage::raw
const object_type * raw() const noexcept
Direct access to the array of objects.
Definition: storage.hpp:206
entt::storage< entity_type, payload_type >::const_iterator
storage_iterator< true > const_iterator
Constant random access iterator type.
Definition: storage.hpp:168
entt::storage::get
const object_type & get(const entity_type entt) const
Returns the object associated with an entity.
Definition: storage.hpp:322
entt::storage::insert
void insert(It first, It last, const object_type &value={})
Assigns one or more entities to a storage and constructs their objects from a given instance.
Definition: storage.hpp:390
entt::storage< entity_type, payload_type >::const_reverse_iterator
const payload_type * const_reverse_iterator
Constant reverse iterator type.
Definition: storage.hpp:172
entt::storage::try_get
object_type * try_get(const entity_type entt)
Returns a pointer to the object associated with an entity, if any.
Definition: storage.hpp:341
entt::sparse_set::insert
void insert(It first, It last)
Assigns one or more entities to a sparse set.
Definition: sparse_set.hpp:407
entt::storage< Entity, Type, std::enable_if_t< is_eto_eligible_v< Type > > >::insert
void insert(It first, It last, const object_type &={})
Assigns one or more entities to a storage.
Definition: storage.hpp:569
entt::sparse_set::begin
iterator begin() const noexcept
Returns an iterator to the beginning.
Definition: sparse_set.hpp:291
entt::sparse_set::size
size_type size() const noexcept
Returns the number of elements in a sparse set.
Definition: sparse_set.hpp:254
entt::sparse_set::arrange
void arrange(iterator first, iterator last, Apply apply, Compare compare, Sort algo=Sort{}, Args &&... args)
Sort elements according to the given comparison function.
Definition: sparse_set.hpp:540
entt::sparse_set< entity_type >::reverse_iterator
const entity_type * reverse_iterator
Reverse iterator type.
Definition: sparse_set.hpp:184
entt::storage::begin
const_iterator begin() const noexcept
Returns an iterator to the beginning.
Definition: storage.hpp:229
entt::storage::try_get
const object_type * try_get(const entity_type entt) const
Returns a pointer to the object associated with an entity, if any.
Definition: storage.hpp:336
entt::storage::rend
const_reverse_iterator rend() const noexcept
Returns a reverse iterator to the end.
Definition: storage.hpp:301
entt::storage::rbegin
const_reverse_iterator rbegin() const noexcept
Returns a reverse iterator to the beginning.
Definition: storage.hpp:277
entt::sparse_set< entity_type >::iterator
sparse_set_iterator iterator
Random access iterator type.
Definition: sparse_set.hpp:182
entt::storage::get
object_type & get(const entity_type entt)
Returns the object associated with an entity.
Definition: storage.hpp:327
entt::storage::sort
void sort(iterator first, iterator last, Compare compare, Sort algo=Sort{}, Args &&... args)
Sort elements according to the given comparison function.
Definition: storage.hpp:492
entt::storage::rend
reverse_iterator rend() noexcept
Returns a reverse iterator to the end.
Definition: storage.hpp:306
entt::storage::end
const_iterator end() const noexcept
Returns an iterator to the end.
Definition: storage.hpp:254
entt::storage::crend
const_reverse_iterator crend() const noexcept
Returns a reverse iterator to the end.
Definition: storage.hpp:296
entt::sparse_set::shrink_to_fit
void shrink_to_fit()
Requests the removal of unused capacity.
Definition: sparse_set.hpp:220
entt::storage::rbegin
reverse_iterator rbegin() noexcept
Returns a reverse iterator to the beginning.
Definition: storage.hpp:282
entt::storage< Entity, Type, std::enable_if_t< is_eto_eligible_v< Type > > >::emplace
void emplace(const entity_type entt, Args &&... args)
Assigns an entity to a storage and constructs its object.
Definition: storage.hpp:550
entt::sparse_set::erase
void erase(const entity_type entt)
Removes an entity from a sparse set.
Definition: sparse_set.hpp:429
entt
EnTT default namespace.
Definition: algorithm.hpp:13
entt::storage::cbegin
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
Definition: storage.hpp:223
entt::storage::erase
void erase(const entity_type entt)
Removes an entity from a storage and destroys its object.
Definition: storage.hpp:427
entt::storage::end
iterator end() noexcept
Returns an iterator to the end.
Definition: storage.hpp:259
entt::storage::shrink_to_fit
void shrink_to_fit()
Requests the removal of unused capacity.
Definition: storage.hpp:189
entt::storage
Basic storage implementation.
Definition: storage.hpp:49
entt::storage::size_type
std::size_t size_type
Unsigned integer type.
Definition: storage.hpp:164
entt::storage::cend
const_iterator cend() const noexcept
Returns an iterator to the end.
Definition: storage.hpp:249
entt::storage::reserve
void reserve(const size_type cap)
Increases the capacity of a storage.
Definition: storage.hpp:183
entt::sparse_set< entity_type >::size_type
std::size_t size_type
Unsigned integer type.
Definition: sparse_set.hpp:180
entt::sparse_set::index
size_type index(const entity_type entt) const
Returns the position of an entity in a sparse set.
Definition: sparse_set.hpp:371
entt::sparse_set::emplace
void emplace(const entity_type entt)
Assigns an entity to a sparse set.
Definition: sparse_set.hpp:387
entt::storage::emplace
void emplace(const entity_type entt, Args &&... args)
Assigns an entity to a storage and constructs its object.
Definition: storage.hpp:363
entt::operator!=
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
Definition: hashed_string.hpp:227
entt::entt_traits
Entity traits.
Definition: entity.hpp:21
entt::sparse_set::clear
void clear() noexcept
Clears a sparse set.
Definition: sparse_set.hpp:602
entt::operator==
constexpr bool operator==(const Entity entity, null_t other) noexcept
Compares a null object and an entity identifier of any type.
Definition: entity.hpp:184
entt::storage::swap
void swap(const entity_type lhs, const entity_type rhs) override
Swaps entities and objects in the internal packed arrays.
Definition: storage.hpp:446
entt::sparse_set::reserve
void reserve(const size_type cap)
Increases the capacity of a sparse set.
Definition: sparse_set.hpp:206
entt::sparse_set< entity_type >::entity_type
entity_type entity_type
Underlying entity identifier.
Definition: sparse_set.hpp:178
entt::storage::raw
object_type * raw() noexcept
Direct access to the array of objects.
Definition: storage.hpp:211
entt::storage< entity_type, payload_type >::object_type
payload_type object_type
Type of the objects associated with the entities.
Definition: storage.hpp:160
entt::sparse_set::contains
bool contains(const entity_type entt) const
Checks if a sparse set contains an entity.
Definition: sparse_set.hpp:353
entt::storage::insert
void insert(EIt first, EIt last, CIt from, CIt to)
Assigns one or more entities to a storage and constructs their objects from a given range.
Definition: storage.hpp:410
entt::std_sort
Function object to wrap std::sort in a class type.
Definition: algorithm.hpp:24