1#ifndef ENTT_ENTITY_REGISTRY_HPP
2#define ENTT_ENTITY_REGISTRY_HPP
14#include "../config/config.h"
15#include "../container/dense_map.hpp"
16#include "../core/algorithm.hpp"
17#include "../core/any.hpp"
18#include "../core/fwd.hpp"
19#include "../core/iterator.hpp"
20#include "../core/memory.hpp"
21#include "../core/type_info.hpp"
22#include "../core/type_traits.hpp"
23#include "../core/utility.hpp"
28#include "sparse_set.hpp"
38class registry_storage_iterator final {
39 template<
typename Other>
40 friend class registry_storage_iterator;
42 using mapped_type = std::remove_reference_t<decltype(std::declval<It>()->second)>;
45 using value_type = std::pair<id_type, constness_as_t<typename mapped_type::element_type, mapped_type> &>;
46 using pointer = input_iterator_pointer<value_type>;
47 using reference = value_type;
48 using difference_type = std::ptrdiff_t;
49 using iterator_category = std::input_iterator_tag;
50 using iterator_concept = std::random_access_iterator_tag;
52 constexpr registry_storage_iterator() noexcept
55 constexpr registry_storage_iterator(It iter) noexcept
58 template<
typename Other,
typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
59 constexpr registry_storage_iterator(
const registry_storage_iterator<Other> &other) noexcept
60 : registry_storage_iterator{other.it} {}
62 constexpr registry_storage_iterator &operator++() noexcept {
66 constexpr registry_storage_iterator operator++(
int)
noexcept {
67 const registry_storage_iterator orig = *
this;
68 return ++(*this), orig;
71 constexpr registry_storage_iterator &operator--() noexcept {
75 constexpr registry_storage_iterator operator--(
int)
noexcept {
76 const registry_storage_iterator orig = *
this;
77 return operator--(), orig;
80 constexpr registry_storage_iterator &operator+=(
const difference_type value)
noexcept {
85 constexpr registry_storage_iterator
operator+(
const difference_type value)
const noexcept {
86 registry_storage_iterator copy = *
this;
87 return (copy += value);
90 constexpr registry_storage_iterator &operator-=(
const difference_type value)
noexcept {
91 return (*
this += -value);
94 constexpr registry_storage_iterator operator-(
const difference_type value)
const noexcept {
95 return (*
this + -value);
98 [[nodiscard]]
constexpr reference operator[](
const difference_type value)
const noexcept {
99 return {it[value].first, *it[value].second};
102 [[nodiscard]]
constexpr reference operator*() const noexcept {
103 return operator[](0);
106 [[nodiscard]]
constexpr pointer operator->() const noexcept {
110 template<
typename Lhs,
typename Rhs>
111 friend constexpr std::ptrdiff_t operator-(
const registry_storage_iterator<Lhs> &,
const registry_storage_iterator<Rhs> &)
noexcept;
113 template<
typename Lhs,
typename Rhs>
114 friend constexpr bool operator==(
const registry_storage_iterator<Lhs> &,
const registry_storage_iterator<Rhs> &)
noexcept;
116 template<
typename Lhs,
typename Rhs>
117 friend constexpr bool operator<(
const registry_storage_iterator<Lhs> &,
const registry_storage_iterator<Rhs> &)
noexcept;
123template<
typename Lhs,
typename Rhs>
124[[nodiscard]]
constexpr std::ptrdiff_t operator-(
const registry_storage_iterator<Lhs> &lhs,
const registry_storage_iterator<Rhs> &rhs)
noexcept {
125 return lhs.it - rhs.it;
128template<
typename Lhs,
typename Rhs>
129[[nodiscard]]
constexpr bool operator==(
const registry_storage_iterator<Lhs> &lhs,
const registry_storage_iterator<Rhs> &rhs)
noexcept {
130 return lhs.it == rhs.it;
133template<
typename Lhs,
typename Rhs>
134[[nodiscard]]
constexpr bool operator!=(
const registry_storage_iterator<Lhs> &lhs,
const registry_storage_iterator<Rhs> &rhs)
noexcept {
135 return !(lhs == rhs);
138template<
typename Lhs,
typename Rhs>
139[[nodiscard]]
constexpr bool operator<(
const registry_storage_iterator<Lhs> &lhs,
const registry_storage_iterator<Rhs> &rhs)
noexcept {
140 return lhs.it < rhs.it;
143template<
typename Lhs,
typename Rhs>
144[[nodiscard]]
constexpr bool operator>(
const registry_storage_iterator<Lhs> &lhs,
const registry_storage_iterator<Rhs> &rhs)
noexcept {
148template<
typename Lhs,
typename Rhs>
149[[nodiscard]]
constexpr bool operator<=(
const registry_storage_iterator<Lhs> &lhs,
const registry_storage_iterator<Rhs> &rhs)
noexcept {
153template<
typename Lhs,
typename Rhs>
154[[nodiscard]]
constexpr bool operator>=(
const registry_storage_iterator<Lhs> &lhs,
const registry_storage_iterator<Rhs> &rhs)
noexcept {
158template<
typename Allocator>
159class registry_context {
160 using alloc_traits = std::allocator_traits<Allocator>;
161 using allocator_type =
typename alloc_traits::template rebind_alloc<std::pair<const id_type, basic_any<0u>>>;
164 explicit registry_context(
const allocator_type &allocator)
167 void clear() noexcept {
171 template<
typename Type,
typename... Args>
172 Type &emplace_as(
const id_type
id, Args &&...args) {
173 return any_cast<Type &>(ctx.try_emplace(
id, std::in_place_type<Type>, std::forward<Args>(args)...).first->second);
176 template<
typename Type,
typename... Args>
177 Type &emplace(Args &&...args) {
178 return emplace_as<Type>(type_id<Type>().hash(), std::forward<Args>(args)...);
181 template<
typename Type>
182 Type &insert_or_assign(
const id_type
id, Type &&value) {
183 return any_cast<std::remove_const_t<std::remove_reference_t<Type>> &>(ctx.insert_or_assign(
id, std::forward<Type>(value)).first->second);
186 template<
typename Type>
187 Type &insert_or_assign(Type &&value) {
188 return insert_or_assign(type_id<Type>().hash(), std::forward<Type>(value));
191 template<
typename Type>
192 bool erase(
const id_type
id = type_id<Type>().hash()) {
193 const auto it = ctx.find(
id);
194 return it != ctx.end() && it->second.info() == type_id<Type>() ? (ctx.erase(it),
true) :
false;
197 template<
typename Type>
198 [[nodiscard]]
const Type &
get(
const id_type
id = type_id<Type>().hash())
const {
199 return any_cast<const Type &>(ctx.at(
id));
202 template<
typename Type>
203 [[nodiscard]] Type &
get(
const id_type
id = type_id<Type>().hash()) {
204 return any_cast<Type &>(ctx.at(
id));
207 template<
typename Type>
208 [[nodiscard]]
const Type *find(
const id_type
id = type_id<Type>().hash())
const {
209 const auto it = ctx.find(
id);
210 return it != ctx.cend() ? any_cast<const Type>(&it->second) : nullptr;
213 template<
typename Type>
214 [[nodiscard]] Type *find(
const id_type
id = type_id<Type>().hash()) {
215 const auto it = ctx.find(
id);
216 return it != ctx.end() ? any_cast<Type>(&it->second) : nullptr;
219 template<
typename Type>
220 [[nodiscard]]
bool contains(
const id_type
id = type_id<Type>().hash())
const {
221 const auto it = ctx.find(
id);
222 return it != ctx.cend() && it->second.info() == type_id<Type>();
226 dense_map<id_type, basic_any<0u>, identity, std::equal_to<>, allocator_type> ctx;
237template<
typename Entity,
typename Allocator>
240 using alloc_traits = std::allocator_traits<Allocator>;
241 static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>,
"Invalid value type");
247 template<
typename Type>
249 static_assert(std::is_same_v<Type, std::decay_t<Type>>,
"Non-decayed types not allowed");
251 if constexpr(std::is_same_v<Type, entity_type>) {
257 if(
auto it = pools.find(
id); it != pools.cend()) {
258 ENTT_ASSERT(it->second->info() ==
type_id<Type>(),
"Unexpected type");
262 using alloc_type =
typename storage_type::allocator_type;
265 if constexpr(std::is_void_v<Type> && !std::is_constructible_v<alloc_type, allocator_type>) {
267 cpool = std::allocate_shared<storage_type>(
get_allocator(), alloc_type{});
272 pools.emplace(
id, cpool);
279 template<
typename Type>
281 static_assert(std::is_same_v<Type, std::decay_t<Type>>,
"Non-decayed types not allowed");
283 if constexpr(std::is_same_v<Type, entity_type>) {
287 if(
const auto it = pools.find(
id); it != pools.cend()) {
288 ENTT_ASSERT(it->second->info() ==
type_id<Type>(),
"Unexpected type");
297 entities.bind(*
this);
299 for(
auto &&curr: pools) {
300 curr.second->bind(*
this);
316 using context = internal::registry_context<allocator_type>;
326 template<
typename Type>
349 entities{allocator} {
362 : vars{std::move(other.vars)},
363 pools{std::move(other.pools)},
364 groups{std::move(other.groups)},
365 entities{std::move(other.entities)} {
395 swap(vars, other.vars);
396 swap(pools, other.pools);
397 swap(groups, other.groups);
398 swap(entities, other.entities);
409 return entities.get_allocator();
421 return iterable{pools.begin(), pools.end()};
435 return const_cast<common_type *
>(std::as_const(*this).storage(
id));
444 const auto it = pools.
find(
id);
445 return it == pools.cend() ? nullptr : it->second.get();
454 template<
typename Type>
456 return assure<std::remove_const_t<Type>>(id);
465 template<
typename Type>
467 return assure<std::remove_const_t<Type>>(id);
477 return !(pools.erase(
id) == 0u);
486 return static_cast<size_type>(entities.find(
entt).index()) < entities.free_list();
496 return entities.current(
entt);
504 return entities.generate();
517 return entities.generate(hint);
529 template<
typename It>
531 entities.generate(std::move(first), std::move(last));
545 for(
size_type pos = pools.size(); pos != 0u; --pos) {
549 entities.erase(
entt);
550 return entities.current(
entt);
580 template<
typename It>
582 const auto to = entities.sort_as(first, last);
585 for(
auto &&curr: pools) {
586 curr.second->remove(from, to);
589 entities.erase(from, to);
607 template<
typename Type,
typename... Args>
609 ENTT_ASSERT(
valid(
entt),
"Invalid entity");
610 return assure<Type>().emplace(
entt, std::forward<Args>(args)...);
623 template<
typename Type,
typename It>
625 ENTT_ASSERT(std::all_of(first, last, [
this](
const auto entt) {
return valid(
entt); }),
"Invalid entity");
626 assure<Type>().insert(std::move(first), std::move(last));
640 template<
typename Type,
typename It>
641 void insert(It first, It last,
const Type &value) {
642 ENTT_ASSERT(std::all_of(first, last, [
this](
const auto entt) {
return valid(
entt); }),
"Invalid entity");
643 assure<Type>().insert(std::move(first), std::move(last), value);
658 template<typename Type, typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, Type>>>
659 void insert(EIt first, EIt last, CIt from) {
660 ENTT_ASSERT(std::all_of(first, last, [
this](
const auto entt) {
return valid(
entt); }),
"Invalid entity");
661 assure<Type>().insert(first, last, from);
676 template<
typename Type,
typename... Args>
678 auto &cpool = assure<Type>();
679 ENTT_ASSERT(
valid(
entt),
"Invalid entity");
680 return cpool.contains(
entt) ? cpool.patch(
entt, [&args...](
auto &...curr) { ((curr = Type{std::forward<Args>(args)...}), ...); }) : cpool.
emplace(
entt, std::forward<Args>(args)...);
702 template<
typename Type,
typename... Func>
704 return assure<Type>().patch(
entt, std::forward<Func>(func)...);
722 template<
typename Type,
typename... Args>
724 return patch<Type>(
entt, [&args...](
auto &...curr) { ((curr = Type{std::forward<Args>(args)...}), ...); });
734 template<
typename Type,
typename... Other>
751 template<
typename Type,
typename... Other,
typename It>
755 if constexpr(std::is_same_v<It, typename common_type::iterator>) {
756 std::array cpools{
static_cast<common_type *
>(&assure<Type>()),
static_cast<common_type *
>(&assure<Other>())...};
758 for(
auto from = cpools.begin(), to = cpools.end(); from != to; ++from) {
759 if constexpr(
sizeof...(Other) != 0u) {
760 if((*from)->data() == first.data()) {
761 std::swap((*from), cpools.back());
765 count += (*from)->remove(first, last);
769 for(
auto cpools = std::forward_as_tuple(assure<Type>(), assure<Other>()...); first != last; ++first) {
770 count += std::apply([
entt = *first](
auto &...curr) {
return (curr.remove(
entt) + ... + 0u); }, cpools);
788 template<
typename Type,
typename... Other>
790 (assure<Type>().erase(
entt), (assure<Other>().erase(
entt), ...));
804 template<
typename Type,
typename... Other,
typename It>
806 if constexpr(std::is_same_v<It, typename common_type::iterator>) {
807 std::array cpools{
static_cast<common_type *
>(&assure<Type>()),
static_cast<common_type *
>(&assure<Other>())...};
809 for(
auto from = cpools.begin(), to = cpools.end(); from != to; ++from) {
810 if constexpr(
sizeof...(Other) != 0u) {
811 if((*from)->data() == first.data()) {
812 std::swap(*from, cpools.back());
816 (*from)->erase(first, last);
819 for(
auto cpools = std::forward_as_tuple(assure<Type>(), assure<Other>()...); first != last; ++first) {
820 std::apply([
entt = *first](
auto &...curr) { (curr.erase(
entt), ...); }, cpools);
840 template<
typename Func>
842 for(
auto [
id, cpool]:
storage()) {
843 if(cpool.contains(
entt) && func(
id, std::as_const(cpool))) {
854 template<
typename... Type>
856 if constexpr(
sizeof...(Type) == 0u) {
857 for(
auto &&curr: pools) {
858 curr.second->compact();
861 (assure<Type>().compact(), ...);
871 template<
typename... Type>
873 if constexpr(
sizeof...(Type) == 1u) {
874 auto *cpool = assure<std::remove_const_t<Type>...>();
875 return cpool && cpool->contains(
entt);
888 template<
typename... Type>
904 template<
typename... Type>
906 if constexpr(
sizeof...(Type) == 1u) {
907 return (assure<std::remove_const_t<Type>>()->
get(
entt), ...);
914 template<
typename... Type>
916 if constexpr(
sizeof...(Type) == 1u) {
938 template<
typename Type,
typename... Args>
940 auto &cpool = assure<Type>();
941 ENTT_ASSERT(
valid(
entt),
"Invalid entity");
942 return cpool.contains(
entt) ? cpool.get(
entt) : cpool.emplace(
entt, std::forward<Args>(args)...);
955 template<
typename... Type>
957 if constexpr(
sizeof...(Type) == 1u) {
958 const auto *cpool = assure<std::remove_const_t<Type>...>();
959 return (cpool && cpool->contains(
entt)) ? std::addressof(cpool->get(
entt)) :
nullptr;
966 template<
typename... Type>
968 if constexpr(
sizeof...(Type) == 1u) {
969 return (
const_cast<Type *
>(std::as_const(*this).template
try_get<Type>(
entt)), ...);
979 template<
typename... Type>
981 if constexpr(
sizeof...(Type) == 0u) {
982 for(
size_type pos = pools.size(); pos; --pos) {
986 const auto elem = entities.each();
987 entities.erase(elem.begin().base(), elem.end().base());
989 (assure<Type>().clear(), ...);
999 return std::none_of(pools.cbegin(), pools.cend(), [
entt](
auto &&curr) { return curr.second->contains(entt); });
1021 template<
typename Type>
1023 return assure<Type>(
id).on_construct();
1045 template<
typename Type>
1047 return assure<Type>(
id).on_update();
1069 template<
typename Type>
1071 return assure<Type>(
id).on_destroy();
1081 template<
typename Type,
typename... Other,
typename... Exclude>
1085 [&elem](
const auto *...curr) { ((curr ? elem.storage(*curr) :
void()), ...); }(assure<std::remove_const_t<Exclude>>()..., assure<std::remove_const_t<Other>>()..., assure<std::remove_const_t<Type>>());
1090 template<
typename Type,
typename... Other,
typename... Exclude>
1091 [[nodiscard]] basic_view<get_t<storage_for_type<Type>, storage_for_type<Other>...>, exclude_t<storage_for_type<Exclude>...>>
1093 return {assure<std::remove_const_t<Type>>(), assure<std::remove_const_t<Other>>()..., assure<std::remove_const_t<Exclude>>()...};
1103 template<
typename... Owned,
typename... Get,
typename... Exclude>
1104 basic_group<owned_t<storage_for_type<Owned>...>, get_t<storage_for_type<Get>...>, exclude_t<storage_for_type<Exclude>...>>
1106 using group_type = basic_group<owned_t<storage_for_type<Owned>...>, get_t<storage_for_type<Get>...>, exclude_t<storage_for_type<Exclude>...>>;
1107 using handler_type =
typename group_type::handler;
1109 if(
auto it = groups.find(group_type::group_id()); it != groups.cend()) {
1110 return {*std::static_pointer_cast<handler_type>(it->second)};
1113 std::shared_ptr<handler_type> handler{};
1115 if constexpr(
sizeof...(Owned) == 0u) {
1116 handler = std::allocate_shared<handler_type>(get_allocator(), get_allocator(), std::forward_as_tuple(assure<std::remove_const_t<Get>>()...), std::forward_as_tuple(assure<std::remove_const_t<Exclude>>()...));
1118 handler = std::allocate_shared<handler_type>(get_allocator(), std::forward_as_tuple(assure<std::remove_const_t<Owned>>()..., assure<std::remove_const_t<Get>>()...), std::forward_as_tuple(assure<std::remove_const_t<Exclude>>()...));
1119 ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [](
const auto &data) { return !(data.second->owned(type_id<Owned>().hash()) || ...); }),
"Conflicting groups");
1122 groups.emplace(group_type::group_id(), handler);
1127 template<
typename... Owned,
typename... Get,
typename... Exclude>
1128 [[nodiscard]] basic_group<owned_t<storage_for_type<const Owned>...>, get_t<storage_for_type<const Get>...>, exclude_t<storage_for_type<const Exclude>...>>
1130 using group_type = basic_group<owned_t<storage_for_type<const Owned>...>, get_t<storage_for_type<const Get>...>, exclude_t<storage_for_type<const Exclude>...>>;
1131 using handler_type =
typename group_type::handler;
1133 if(
auto it = groups.find(group_type::group_id()); it != groups.cend()) {
1134 return {*std::static_pointer_cast<handler_type>(it->second)};
1146 template<
typename... Type>
1148 return std::any_of(groups.cbegin(), groups.cend(), [](
auto &&data) { return (data.second->owned(type_id<Type>().hash()) || ...); });
1184 template<
typename Type,
typename Compare,
typename Sort =
std_sort,
typename... Args>
1185 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
1186 ENTT_ASSERT(!
owned<Type>(),
"Cannot sort owned storage");
1187 auto &cpool = assure<Type>();
1189 if constexpr(std::is_invocable_v<Compare,
decltype(cpool.get({})),
decltype(cpool.get({}))>) {
1190 auto comp = [&cpool, compare = std::move(compare)](
const auto lhs,
const auto rhs) {
return compare(std::as_const(cpool.get(lhs)), std::as_const(cpool.get(rhs))); };
1191 cpool.sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
1193 cpool.sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
1210 template<
typename To,
typename From>
1212 ENTT_ASSERT(!
owned<To>(),
"Cannot sort owned storage");
1213 const base_type &cpool = assure<From>();
1214 assure<To>().sort_as(cpool.
begin(), cpool.
end());
1232 pool_container_type pools;
1233 group_container_type groups;
1234 storage_for_type<entity_type> entities;
static constexpr value_type construct(const entity_type entity, const version_type version) noexcept
Constructs an identifier from its parts.
static constexpr value_type next(const value_type value) noexcept
Returns the successor of a given identifier.
static constexpr entity_type to_entity(const value_type value) noexcept
Returns the entity part once converted to the underlying type.
typename Traits::value_type value_type
Value type.
typename Traits::version_type version_type
Underlying version type.
context & ctx() noexcept
Returns the context object, that is, a general purpose container.
auto on_destroy(const id_type id=type_hash< Type >::value())
Returns a sink object for the given element.
bool any_of(const entity_type entt) const
Check if an entity is part of at least one given storage.
bool owned() const
Checks whether the given elements belong to any group.
decltype(auto) get_or_emplace(const entity_type entt, Args &&...args)
Returns a reference to the given element for an entity.
bool orphan(const entity_type entt) const
Checks if an entity has elements assigned.
decltype(auto) replace(const entity_type entt, Args &&...args)
Replaces the given element for an entity.
basic_registry(const size_type count, const allocator_type &allocator=allocator_type{})
Allocates enough memory upon construction to store count pools.
auto on_update(const id_type id=type_hash< Type >::value())
Returns a sink object for the given element.
const common_type * storage(const id_type id) const
Finds the storage associated with a given name, if any.
auto try_get(const entity_type entt) const
Returns pointers to the given elements for an entity.
void swap(basic_registry &other) noexcept
Exchanges the contents with those of a given registry.
iterable_adaptor< internal::registry_storage_iterator< typename pool_container_type::iterator > > iterable
decltype(auto) emplace_or_replace(const entity_type entt, Args &&...args)
Assigns or replaces the given element for an entity.
void insert(It first, It last)
Assigns each entity in a range the given element.
iterable storage() noexcept
Returns an iterable object to use to visit a registry.
bool valid(const entity_type entt) const
Checks if an identifier refers to a valid entity.
bool all_of(const entity_type entt) const
Check if an entity is part of all the given storage.
void erase_if(const entity_type entt, Func func)
Erases elements satisfying specific criteria from an entity.
version_type destroy(const entity_type entt)
Destroys an entity and releases its identifier.
typename traits_type::version_type version_type
entity_type create()
Creates a new entity or recycles a destroyed one.
const context & ctx() const noexcept
Returns the context object, that is, a general purpose container.
void sort()
Sorts two pools of elements in the same way.
version_type destroy(const entity_type entt, const version_type version)
Destroys an entity and releases its identifier.
basic_view< get_t< storage_for_type< const Type >, storage_for_type< const Other >... >, exclude_t< storage_for_type< const Exclude >... > > view(exclude_t< Exclude... >=exclude_t{}) const
Returns a view for the given elements.
void create(It first, It last)
Assigns each element in a range an identifier.
size_type remove(It first, It last)
Removes the given elements from all the entities in a range.
entity_type create(const entity_type hint)
Creates a new entity or recycles a destroyed one.
void clear()
Clears a whole registry or the pools for the given elements.
bool reset(const id_type id)
Discards the storage associated with a given name, if any.
decltype(auto) patch(const entity_type entt, Func &&...func)
Patches the given element for an entity.
basic_group< owned_t< storage_for_type< const Owned >... >, get_t< storage_for_type< const Get >... >, exclude_t< storage_for_type< const Exclude >... > > group_if_exists(get_t< Get... >=get_t{}, exclude_t< Exclude... >=exclude_t{}) const
Returns a group for the given elements.
size_type remove(const entity_type entt)
Removes the given elements from an entity.
basic_registry & operator=(basic_registry &&other) noexcept
Move assignment operator.
basic_view< get_t< storage_for_type< Type >, storage_for_type< Other >... >, exclude_t< storage_for_type< Exclude >... > > view(exclude_t< Exclude... >=exclude_t{})
Returns a view for the given elements.
auto try_get(const entity_type entt)
Returns pointers to the given elements for an entity.
common_type * storage(const id_type id)
Finds the storage associated with a given name, if any.
void destroy(It first, It last)
Destroys all entities in a range and releases their identifiers.
decltype(auto) get(const entity_type entt)
Returns references to the given elements for an entity.
typename storage_for< Type, Entity, typename alloc_traits::template rebind_alloc< std::remove_const_t< Type > > >::type storage_for_type
void erase(It first, It last)
Erases the given elements from all the entities in a range.
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sorts the elements of a given element.
constexpr allocator_type get_allocator() const noexcept
Returns the associated allocator.
decltype(auto) emplace(const entity_type entt, Args &&...args)
Assigns the given element to an entity.
basic_registry & operator=(const basic_registry &)=delete
Default copy assignment operator, deleted on purpose.
basic_registry(const allocator_type &allocator)
Constructs an empty registry with a given allocator.
auto on_construct(const id_type id=type_hash< Type >::value())
Returns a sink object for the given element.
storage_for_type< Type > & storage(const id_type id=type_hash< Type >::value())
Returns the storage for a given element type.
void insert(It first, It last, const Type &value)
Assigns each entity in a range the given element.
typename traits_type::value_type entity_type
decltype(auto) get(const entity_type entt) const
Returns references to the given elements for an entity.
basic_registry(basic_registry &&other) noexcept
Move constructor.
void compact()
Removes all tombstones from a registry or only the pools for the given elements.
const_iterable storage() const noexcept
Returns an iterable object to use to visit a registry.
~basic_registry()=default
Default destructor.
version_type current(const entity_type entt) const
Returns the actual version for an identifier.
basic_group< owned_t< storage_for_type< Owned >... >, get_t< storage_for_type< Get >... >, exclude_t< storage_for_type< Exclude >... > > group(get_t< Get... >=get_t{}, exclude_t< Exclude... >=exclude_t{})
Returns a group for the given elements.
const storage_for_type< Type > * storage(const id_type id=type_hash< Type >::value()) const
Returns the storage for a given element type, if any.
void insert(EIt first, EIt last, CIt from)
Assigns each entity in a range the given elements.
basic_registry(const basic_registry &)=delete
Default copy constructor, deleted on purpose.
internal::registry_context< allocator_type > context
iterable_adaptor< internal::registry_storage_iterator< typename pool_container_type::const_iterator > > const_iterable
basic_registry()
Default constructor.
void erase(const entity_type entt)
Erases the given elements from an entity.
Sparse set implementation.
iterator begin() const noexcept
Returns an iterator to the beginning.
iterator end() const noexcept
Returns an iterator to the end.
std::ptrdiff_t difference_type
Signed integer type.
const_iterator find(const entity_type entt) const noexcept
Finds an entity.
Associative container for key-value pairs with unique keys.
void reserve(const size_type cnt)
Reserves space for at least the specified number of elements and regenerates the hash table.
std::shared_ptr< base_type > mapped_type
std::ptrdiff_t difference_type
std::uint32_t id_type
Alias declaration for type identifiers.
constexpr tombstone_t tombstone
Compile-time constant for tombstone entities.
constexpr get_t< Type... > get
Variable template for lists of observed elements.
constexpr bool operator<=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator<(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr type_list< Type..., Other... > operator+(type_list< Type... >, type_list< Other... >)
Concatenates multiple type lists.
constexpr owned_t< Type... > owned
Variable template for lists of owned elements.
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator>=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
const type_info & type_id() noexcept
Returns the type info object associated to a given type.
constexpr bool operator>(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
Alias for exclusion lists.
Alias for lists of observed elements.
Identity function object (waiting for C++20).
Utility class to create an iterable object from a pair of iterators.
Function object to wrap std::sort in a class type.
Provides a common way to define storage types.
static constexpr id_type value() noexcept
Returns the numeric representation of a given type.