1 #ifndef ENTT_ENTITY_STORAGE_HPP
2 #define ENTT_ENTITY_STORAGE_HPP
10 #include <type_traits>
11 #include "../config/config.h"
12 #include "../core/algorithm.hpp"
13 #include "../core/type_traits.hpp"
15 #include "sparse_set.hpp"
48 template<
typename Entity,
typename Type,
typename = std::
void_t<>>
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");
56 class storage_iterator final {
57 friend class storage<Entity, Type>;
59 using instance_type = std::conditional_t<Const, const std::vector<Type>, std::vector<Type>>;
60 using index_type =
typename traits_type::difference_type;
62 storage_iterator(instance_type &ref,
const index_type idx) ENTT_NOEXCEPT
63 : instances{&ref},
index{idx}
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;
73 storage_iterator() ENTT_NOEXCEPT =
default;
75 storage_iterator & operator++() ENTT_NOEXCEPT {
76 return --
index, *
this;
79 storage_iterator operator++(
int) ENTT_NOEXCEPT {
80 storage_iterator orig = *
this;
81 return ++(*this), orig;
84 storage_iterator & operator--() ENTT_NOEXCEPT {
85 return ++
index, *
this;
88 storage_iterator operator--(
int) ENTT_NOEXCEPT {
89 storage_iterator orig = *
this;
90 return operator--(), orig;
93 storage_iterator & operator+=(
const difference_type value) ENTT_NOEXCEPT {
98 storage_iterator operator+(
const difference_type value)
const ENTT_NOEXCEPT {
99 storage_iterator copy = *
this;
100 return (copy += value);
103 storage_iterator & operator-=(
const difference_type value) ENTT_NOEXCEPT {
104 return (*
this += -value);
107 storage_iterator operator-(
const difference_type value)
const ENTT_NOEXCEPT {
108 return (*
this + -value);
111 difference_type operator-(
const storage_iterator &other)
const ENTT_NOEXCEPT {
112 return other.index -
index;
115 [[nodiscard]] reference operator[](
const difference_type value)
const ENTT_NOEXCEPT {
117 return (*instances)[pos];
120 [[nodiscard]]
bool operator==(
const storage_iterator &other)
const ENTT_NOEXCEPT {
121 return other.index ==
index;
124 [[nodiscard]]
bool operator!=(
const storage_iterator &other)
const ENTT_NOEXCEPT {
125 return !(*
this == other);
128 [[nodiscard]]
bool operator<(
const storage_iterator &other)
const ENTT_NOEXCEPT {
129 return index > other.index;
132 [[nodiscard]]
bool operator>(
const storage_iterator &other)
const ENTT_NOEXCEPT {
133 return index < other.index;
136 [[nodiscard]]
bool operator<=(
const storage_iterator &other)
const ENTT_NOEXCEPT {
137 return !(*
this > other);
140 [[nodiscard]]
bool operator>=(
const storage_iterator &other)
const ENTT_NOEXCEPT {
141 return !(*
this < other);
144 [[nodiscard]] pointer operator->()
const ENTT_NOEXCEPT {
146 return &(*instances)[pos];
149 [[nodiscard]] reference operator*()
const ENTT_NOEXCEPT {
150 return *operator->();
154 instance_type *instances;
185 instances.reserve(cap);
191 instances.shrink_to_fit();
207 return instances.data();
212 return const_cast<object_type *
>(std::as_const(*this).raw());
273 return instances.data();
283 return instances.data();
297 return crbegin() + instances.size();
307 return rbegin() + instances.size();
362 template<
typename... Args>
364 if constexpr(std::is_aggregate_v<object_type>) {
365 instances.push_back(Type{std::forward<Args>(args)...});
367 instances.emplace_back(std::forward<Args>(args)...);
389 template<
typename It>
391 instances.insert(instances.end(), std::distance(first, last), value);
409 template<
typename EIt,
typename CIt>
410 void insert(EIt first, EIt last, CIt from, CIt to) {
411 instances.insert(instances.end(), from, to);
428 auto other = std::move(instances.back());
430 instances.pop_back();
491 template<
typename Compare,
typename Sort =
std_sort,
typename... Args>
493 ENTT_ASSERT(!(last < first));
494 ENTT_ASSERT(!(last >
end()));
497 const auto to = from + std::distance(first, last);
499 const auto apply = [
this](
const auto lhs,
const auto rhs) {
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) {
506 }, std::move(algo), std::forward<Args>(args)...);
508 underlying_type::arrange(from, to, std::move(apply), std::move(compare), std::move(algo), std::forward<Args>(args)...);
519 std::vector<object_type> instances;
524 template<
typename Entity,
typename Type>
525 class storage<Entity, Type, std::enable_if_t<is_eto_eligible_v<Type>>>:
public sparse_set<Entity> {
549 template<
typename... Args>
551 [[maybe_unused]]
object_type instance{std::forward<Args>(args)...};
568 template<
typename It>
virtual void swap(const entity_type lhs, const entity_type rhs)
Swaps two entities in the internal packed array.
const_reverse_iterator crbegin() const noexcept
Returns a reverse iterator to the beginning.
void clear()
Clears a storage.
Basic sparse set implementation.
iterator begin() noexcept
Returns an iterator to the beginning.
Type object_type
Type of the objects associated with the entities.
const object_type * raw() const noexcept
Direct access to the array of objects.
storage_iterator< true > const_iterator
Constant random access iterator type.
const object_type & get(const entity_type entt) const
Returns the object associated with an entity.
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.
const payload_type * const_reverse_iterator
Constant reverse iterator type.
object_type * try_get(const entity_type entt)
Returns a pointer to the object associated with an entity, if any.
void insert(It first, It last)
Assigns one or more entities to a sparse set.
void insert(It first, It last, const object_type &={})
Assigns one or more entities to a storage.
iterator begin() const noexcept
Returns an iterator to the beginning.
size_type size() const noexcept
Returns the number of elements in a sparse set.
void arrange(iterator first, iterator last, Apply apply, Compare compare, Sort algo=Sort{}, Args &&... args)
Sort elements according to the given comparison function.
const entity_type * reverse_iterator
Reverse iterator type.
const_iterator begin() const noexcept
Returns an iterator to the beginning.
const object_type * try_get(const entity_type entt) const
Returns a pointer to the object associated with an entity, if any.
const_reverse_iterator rend() const noexcept
Returns a reverse iterator to the end.
const_reverse_iterator rbegin() const noexcept
Returns a reverse iterator to the beginning.
sparse_set_iterator iterator
Random access iterator type.
object_type & get(const entity_type entt)
Returns the object associated with an entity.
void sort(iterator first, iterator last, Compare compare, Sort algo=Sort{}, Args &&... args)
Sort elements according to the given comparison function.
reverse_iterator rend() noexcept
Returns a reverse iterator to the end.
const_iterator end() const noexcept
Returns an iterator to the end.
const_reverse_iterator crend() const noexcept
Returns a reverse iterator to the end.
void shrink_to_fit()
Requests the removal of unused capacity.
reverse_iterator rbegin() noexcept
Returns a reverse iterator to the beginning.
void emplace(const entity_type entt, Args &&... args)
Assigns an entity to a storage and constructs its object.
void erase(const entity_type entt)
Removes an entity from a sparse set.
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
void erase(const entity_type entt)
Removes an entity from a storage and destroys its object.
iterator end() noexcept
Returns an iterator to the end.
void shrink_to_fit()
Requests the removal of unused capacity.
Basic storage implementation.
std::size_t size_type
Unsigned integer type.
const_iterator cend() const noexcept
Returns an iterator to the end.
void reserve(const size_type cap)
Increases the capacity of a storage.
std::size_t size_type
Unsigned integer type.
size_type index(const entity_type entt) const
Returns the position of an entity in a sparse set.
void emplace(const entity_type entt)
Assigns an entity to a sparse set.
void emplace(const entity_type entt, Args &&... args)
Assigns an entity to a storage and constructs its object.
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
void clear() noexcept
Clears a sparse set.
constexpr bool operator==(const Entity entity, null_t other) noexcept
Compares a null object and an entity identifier of any type.
void swap(const entity_type lhs, const entity_type rhs) override
Swaps entities and objects in the internal packed arrays.
void reserve(const size_type cap)
Increases the capacity of a sparse set.
entity_type entity_type
Underlying entity identifier.
object_type * raw() noexcept
Direct access to the array of objects.
payload_type object_type
Type of the objects associated with the entities.
bool contains(const entity_type entt) const
Checks if a sparse set contains an entity.
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.
Function object to wrap std::sort in a class type.