Explorar el Código

entity identifiers as enum classes (close #256)

Michele Caini hace 6 años
padre
commit
11d18fa1af

+ 7 - 5
docs/md/entity.md

@@ -137,9 +137,9 @@ use as-is and store around if needed. Do not try to inspect an entity
 identifier, its format can change in future and a registry offers all the
 identifier, its format can change in future and a registry offers all the
 functionalities to query them out-of-the-box. The underlying type of an entity
 functionalities to query them out-of-the-box. The underlying type of an entity
 (either `std::uint16_t`, `std::uint32_t` or `std::uint64_t`) can be specified
 (either `std::uint16_t`, `std::uint32_t` or `std::uint64_t`) can be specified
-when defining a registry (actually `entt::registry` is nothing more than an
-alias for `entt::basic_registry<entt::entity>` and `entt::entity` is an alias
-for `std::uint32_t`).<br/>
+when defining a registry. In fact, an `entt::registry` is nothing more than an
+alias for `entt::basic_registry<entt::entity>` and `entt::entity` is a distinct
+type that implements the concept of _entity identifier_.<br/>
 Components (the _C_ of an _ECS_) should be plain old data structures or more
 Components (the _C_ of an _ECS_) should be plain old data structures or more
 complex and movable data structures with a proper constructor. Actually, the
 complex and movable data structures with a proper constructor. Actually, the
 sole requirement of a component type is that it must be both move constructible
 sole requirement of a component type is that it must be both move constructible
@@ -162,12 +162,14 @@ A registry can store and manage entities, as well as create views and groups to
 iterate the underlying data structures.<br/>
 iterate the underlying data structures.<br/>
 The class template `basic_registry` lets users decide what's the preferred type
 The class template `basic_registry` lets users decide what's the preferred type
 to represent an entity. Because `std::uint32_t` is large enough for almost all
 to represent an entity. Because `std::uint32_t` is large enough for almost all
-the cases, there exists also the alias `entt::entity` for it, as well as the
+the cases, there exists also the type `entt::entity` for it, as well as the
 alias `entt::registry` for `entt::basic_registry<entt::entity>`.
 alias `entt::registry` for `entt::basic_registry<entt::entity>`.
 
 
 Entities are represented by _entity identifiers_. An entity identifier is an
 Entities are represented by _entity identifiers_. An entity identifier is an
 opaque type that users should not inspect or modify in any way. It carries
 opaque type that users should not inspect or modify in any way. It carries
-information about the entity itself and its version.
+information about the entity itself and its version.<br/>
+User defined identifiers can be introduced by means of the `ENTT_ENTITY_TYPE`
+macro if needed.
 
 
 A registry can be used both to construct and to destroy entities:
 A registry can be used both to construct and to destroy entities:
 
 

+ 1 - 1
src/entt/entity/actor.hpp

@@ -184,7 +184,7 @@ struct basic_actor {
 
 
 private:
 private:
     registry_type *reg;
     registry_type *reg;
-    Entity entt;
+    entity_type entt;
 };
 };
 
 
 
 

+ 17 - 2
src/entt/entity/entity.hpp

@@ -3,6 +3,7 @@
 
 
 
 
 #include <cstdint>
 #include <cstdint>
+#include <type_traits>
 #include "../config/config.h"
 #include "../config/config.h"
 
 
 
 
@@ -109,8 +110,8 @@ namespace internal {
 struct null {
 struct null {
     template<typename Entity>
     template<typename Entity>
     constexpr operator Entity() const ENTT_NOEXCEPT {
     constexpr operator Entity() const ENTT_NOEXCEPT {
-        using traits_type = entt_traits<Entity>;
-        return traits_type::entity_mask | (traits_type::version_mask << traits_type::entity_shift);
+        using traits_type = entt_traits<std::underlying_type_t<Entity>>;
+        return Entity{traits_type::entity_mask | (traits_type::version_mask << traits_type::entity_shift)};
     }
     }
 
 
     constexpr bool operator==(null) const ENTT_NOEXCEPT {
     constexpr bool operator==(null) const ENTT_NOEXCEPT {
@@ -164,6 +165,20 @@ constexpr bool operator!=(const Entity entity, null other) ENTT_NOEXCEPT {
 constexpr auto null = internal::null{};
 constexpr auto null = internal::null{};
 
 
 
 
+/**
+ * @brief Defines an enum class to use for entity identifiers and a dedicate
+ * `to_integer` function to convert the identifiers to their underlying type.
+ * @param clazz The name to use for the enum class.
+ * @param type The underlying type for the enum class.
+ */
+#define ENTT_ENTITY_TYPE(clazz, type)\
+    enum class clazz: type {};\
+    constexpr auto to_integer(const clazz entt) ENTT_NOEXCEPT {\
+        using traits_type = entt_traits<std::underlying_type_t<clazz>>;\
+        return typename traits_type::entity_type(entt);\
+    }
+
+
 }
 }
 
 
 
 

+ 2 - 1
src/entt/entity/fwd.hpp

@@ -4,6 +4,7 @@
 
 
 #include <cstdint>
 #include <cstdint>
 #include "../config/config.h"
 #include "../config/config.h"
+#include "entity.hpp"
 
 
 
 
 namespace entt {
 namespace entt {
@@ -49,7 +50,7 @@ template<typename>
 class basic_continuous_loader;
 class basic_continuous_loader;
 
 
 /*! @brief Alias declaration for the most common use case. */
 /*! @brief Alias declaration for the most common use case. */
-using entity = std::uint32_t;
+ENTT_ENTITY_TYPE(entity, std::uint32_t)
 
 
 /*! @brief Alias declaration for the most common use case. */
 /*! @brief Alias declaration for the most common use case. */
 using registry = basic_registry<entity>;
 using registry = basic_registry<entity>;

+ 2 - 3
src/entt/entity/observer.hpp

@@ -165,7 +165,6 @@ constexpr basic_collector<> collector{};
  */
  */
 template<typename Entity>
 template<typename Entity>
 class basic_observer {
 class basic_observer {
-    using traits_type = entt_traits<Entity>;
     using payload_type = std::uint32_t;
     using payload_type = std::uint32_t;
 
 
     template<typename>
     template<typename>
@@ -257,7 +256,7 @@ class basic_observer {
 
 
 public:
 public:
     /*! @brief Underlying entity identifier. */
     /*! @brief Underlying entity identifier. */
-    using entity_type = typename traits_type::entity_type;
+    using entity_type = Entity;
     /*! @brief Unsigned integer type. */
     /*! @brief Unsigned integer type. */
     using size_type = typename sparse_set<Entity>::size_type;
     using size_type = typename sparse_set<Entity>::size_type;
     /*! @brief Input iterator type. */
     /*! @brief Input iterator type. */
@@ -428,7 +427,7 @@ public:
 
 
 private:
 private:
     basic_registry<entity_type> *target;
     basic_registry<entity_type> *target;
-    void(* release)(basic_observer &, basic_registry<Entity> &);
+    void(* release)(basic_observer &, basic_registry<entity_type> &);
     storage<entity_type, payload_type> view;
     storage<entity_type, payload_type> view;
 };
 };
 
 

+ 39 - 35
src/entt/entity/registry.hpp

@@ -7,7 +7,6 @@
 #include <memory>
 #include <memory>
 #include <utility>
 #include <utility>
 #include <cstddef>
 #include <cstddef>
-#include <numeric>
 #include <iterator>
 #include <iterator>
 #include <algorithm>
 #include <algorithm>
 #include <type_traits>
 #include <type_traits>
@@ -44,7 +43,7 @@ template<typename Entity>
 class basic_registry {
 class basic_registry {
     using context_family = family<struct internal_registry_context_family>;
     using context_family = family<struct internal_registry_context_family>;
     using component_family = family<struct internal_registry_component_family>;
     using component_family = family<struct internal_registry_component_family>;
-    using traits_type = entt_traits<Entity>;
+    using traits_type = entt_traits<std::underlying_type_t<Entity>>;
 
 
     template<typename Component>
     template<typename Component>
     struct pool_handler: storage<Entity, Component> {
     struct pool_handler: storage<Entity, Component> {
@@ -214,11 +213,11 @@ class basic_registry {
 
 
     void release(const Entity entity) {
     void release(const Entity entity) {
         // lengthens the implicit list of destroyed entities
         // lengthens the implicit list of destroyed entities
-        const auto entt = entity & traits_type::entity_mask;
-        const auto version = ((entity >> traits_type::entity_shift) + 1) << traits_type::entity_shift;
-        const auto node = (available ? next : ((entt + 1) & traits_type::entity_mask)) | version;
-        entities[entt] = node;
-        next = entt;
+        const auto entt = to_integer(entity) & traits_type::entity_mask;
+        const auto version = ((to_integer(entity) >> traits_type::entity_shift) + 1) << traits_type::entity_shift;
+        const auto node = (available ? to_integer(next) : ((entt + 1) & traits_type::entity_mask)) | version;
+        entities[entt] = Entity{node};
+        next = Entity{entt};
         ++available;
         ++available;
     }
     }
 
 
@@ -284,7 +283,7 @@ class basic_registry {
 
 
 public:
 public:
     /*! @brief Underlying entity identifier. */
     /*! @brief Underlying entity identifier. */
-    using entity_type = typename traits_type::entity_type;
+    using entity_type = Entity;
     /*! @brief Underlying version type. */
     /*! @brief Underlying version type. */
     using version_type = typename traits_type::version_type;
     using version_type = typename traits_type::version_type;
     /*! @brief Unsigned integer type. */
     /*! @brief Unsigned integer type. */
@@ -473,7 +472,7 @@ public:
      * @return True if the identifier is valid, false otherwise.
      * @return True if the identifier is valid, false otherwise.
      */
      */
     bool valid(const entity_type entity) const ENTT_NOEXCEPT {
     bool valid(const entity_type entity) const ENTT_NOEXCEPT {
-        const auto pos = size_type(entity & traits_type::entity_mask);
+        const auto pos = size_type(to_integer(entity) & traits_type::entity_mask);
         return (pos < entities.size() && entities[pos] == entity);
         return (pos < entities.size() && entities[pos] == entity);
     }
     }
 
 
@@ -483,7 +482,7 @@ public:
      * @return The entity identifier without the version.
      * @return The entity identifier without the version.
      */
      */
     static entity_type entity(const entity_type entity) ENTT_NOEXCEPT {
     static entity_type entity(const entity_type entity) ENTT_NOEXCEPT {
-        return entity & traits_type::entity_mask;
+        return entity_type{to_integer(entity) & traits_type::entity_mask};
     }
     }
 
 
     /**
     /**
@@ -492,7 +491,7 @@ public:
      * @return The version stored along with the given entity identifier.
      * @return The version stored along with the given entity identifier.
      */
      */
     static version_type version(const entity_type entity) ENTT_NOEXCEPT {
     static version_type version(const entity_type entity) ENTT_NOEXCEPT {
-        return version_type(entity >> traits_type::entity_shift);
+        return version_type(to_integer(entity) >> traits_type::entity_shift);
     }
     }
 
 
     /**
     /**
@@ -509,9 +508,9 @@ public:
      * @return Actual version for the given entity identifier.
      * @return Actual version for the given entity identifier.
      */
      */
     version_type current(const entity_type entity) const ENTT_NOEXCEPT {
     version_type current(const entity_type entity) const ENTT_NOEXCEPT {
-        const auto pos = size_type(entity & traits_type::entity_mask);
+        const auto pos = size_type(to_integer(entity) & traits_type::entity_mask);
         ENTT_ASSERT(pos < entities.size());
         ENTT_ASSERT(pos < entities.size());
-        return version_type(entities[pos] >> traits_type::entity_shift);
+        return version_type(to_integer(entities[pos]) >> traits_type::entity_shift);
     }
     }
 
 
     /**
     /**
@@ -541,16 +540,16 @@ public:
         entity_type entity;
         entity_type entity;
 
 
         if(available) {
         if(available) {
-            const auto entt = next;
-            const auto version = entities[entt] & (traits_type::version_mask << traits_type::entity_shift);
-            next = entities[entt] & traits_type::entity_mask;
-            entity = entt | version;
+            const auto entt = to_integer(next);
+            const auto version = to_integer(entities[entt]) & (traits_type::version_mask << traits_type::entity_shift);
+            next = entity_type{to_integer(entities[entt]) & traits_type::entity_mask};
+            entity = entity_type{entt | version};
             entities[entt] = entity;
             entities[entt] = entity;
             --available;
             --available;
         } else {
         } else {
             entity = entities.emplace_back(entity_type(entities.size()));
             entity = entities.emplace_back(entity_type(entities.size()));
             // traits_type::entity_mask is reserved to allow for null identifiers
             // traits_type::entity_mask is reserved to allow for null identifiers
-            ENTT_ASSERT(entity < traits_type::entity_mask);
+            ENTT_ASSERT(to_integer(entity) < traits_type::entity_mask);
         }
         }
 
 
         if constexpr(sizeof...(Component) == 0) {
         if constexpr(sizeof...(Component) == 0) {
@@ -584,16 +583,16 @@ public:
 
 
         const auto tail = std::generate_n(first, sz, [&candidate, this]() mutable {
         const auto tail = std::generate_n(first, sz, [&candidate, this]() mutable {
             if constexpr(sizeof...(Component) > 0) {
             if constexpr(sizeof...(Component) > 0) {
-                candidate = std::max(candidate, next);
+                candidate = entity_type{std::max(candidate, next)};
             } else {
             } else {
                 // suppress warnings
                 // suppress warnings
                 (void)candidate;
                 (void)candidate;
             }
             }
 
 
-            const auto entt = next;
-            const auto version = entities[entt] & (traits_type::version_mask << traits_type::entity_shift);
-            next = entities[entt] & traits_type::entity_mask;
-            return (entities[entt] = entt | version);
+            const auto entt = to_integer(next);
+            const auto version = to_integer(entities[entt]) & (traits_type::version_mask << traits_type::entity_shift);
+            next = entity_type{to_integer(entities[entt]) & traits_type::entity_mask};
+            return (entities[entt] = entity_type{entt | version});
         });
         });
 
 
         std::generate(tail, last, [this]() {
         std::generate(tail, last, [this]() {
@@ -1145,8 +1144,8 @@ public:
         if(available) {
         if(available) {
             for(auto pos = entities.size(); pos; --pos) {
             for(auto pos = entities.size(); pos; --pos) {
                 const auto curr = entity_type(pos - 1);
                 const auto curr = entity_type(pos - 1);
-                const auto entity = entities[curr];
-                const auto entt = entity & traits_type::entity_mask;
+                const auto entity = entities[to_integer(curr)];
+                const auto entt = entity_type{to_integer(entity) & traits_type::entity_mask};
 
 
                 if(curr == entt) {
                 if(curr == entt) {
                     func(entity);
                     func(entity);
@@ -1486,13 +1485,17 @@ public:
      */
      */
     entt::basic_snapshot<Entity> snapshot() const ENTT_NOEXCEPT {
     entt::basic_snapshot<Entity> snapshot() const ENTT_NOEXCEPT {
         using follow_fn_type = entity_type(const basic_registry &, const entity_type);
         using follow_fn_type = entity_type(const basic_registry &, const entity_type);
-        const entity_type seed = available ? (next | (entities[next] & (traits_type::version_mask << traits_type::entity_shift))) : next;
+
+        const auto head = to_integer(next);
+        const entity_type seed = available
+                ? entity_type{head | (to_integer(entities[head]) & (traits_type::version_mask << traits_type::entity_shift))}
+                : next;
 
 
         follow_fn_type *follow = [](const basic_registry &reg, const entity_type entity) -> entity_type {
         follow_fn_type *follow = [](const basic_registry &reg, const entity_type entity) -> entity_type {
             const auto &others = reg.entities;
             const auto &others = reg.entities;
-            const auto entt = entity & traits_type::entity_mask;
-            const auto curr = others[entt] & traits_type::entity_mask;
-            return (curr | (others[curr] & (traits_type::version_mask << traits_type::entity_shift)));
+            const auto entt = to_integer(entity) & traits_type::entity_mask;
+            const auto curr = to_integer(others[entt]) & traits_type::entity_mask;
+            return entity_type{curr | (to_integer(others[curr]) & (traits_type::version_mask << traits_type::entity_shift))};
         };
         };
 
 
         return { this, seed, follow };
         return { this, seed, follow };
@@ -1517,23 +1520,24 @@ public:
         using force_fn_type = void(basic_registry &, const entity_type, const bool);
         using force_fn_type = void(basic_registry &, const entity_type, const bool);
 
 
         force_fn_type *force = [](basic_registry &reg, const entity_type entity, const bool destroyed) {
         force_fn_type *force = [](basic_registry &reg, const entity_type entity, const bool destroyed) {
-            using promotion_type = std::conditional_t<sizeof(size_type) >= sizeof(entity_type), size_type, entity_type>;
-            // explicit promotion to avoid warnings with std::uint16_t
-            const auto entt = promotion_type{entity} & traits_type::entity_mask;
+            const auto entt = to_integer(entity) & traits_type::entity_mask;
             auto &others = reg.entities;
             auto &others = reg.entities;
 
 
             if(!(entt < others.size())) {
             if(!(entt < others.size())) {
                 auto curr = others.size();
                 auto curr = others.size();
                 others.resize(entt + 1);
                 others.resize(entt + 1);
-                std::iota(others.data() + curr, others.data() + entt, entity_type(curr));
+
+                std::generate(others.data() + curr, others.data() + entt, [curr]() mutable {
+                    return entity_type(curr++);
+                });
             }
             }
 
 
             others[entt] = entity;
             others[entt] = entity;
 
 
             if(destroyed) {
             if(destroyed) {
                 reg.destroy(entity);
                 reg.destroy(entity);
-                const auto version = entity & (traits_type::version_mask << traits_type::entity_shift);
-                others[entt] = ((others[entt] & traits_type::entity_mask) | version);
+                const auto version = to_integer(entity) & (traits_type::version_mask << traits_type::entity_shift);
+                others[entt] = entity_type{(to_integer(others[entt]) & traits_type::entity_mask) | version};
             }
             }
         };
         };
 
 

+ 3 - 2
src/entt/entity/runtime_view.hpp

@@ -7,6 +7,7 @@
 #include <vector>
 #include <vector>
 #include <utility>
 #include <utility>
 #include <algorithm>
 #include <algorithm>
+#include <type_traits>
 #include "../config/config.h"
 #include "../config/config.h"
 #include "sparse_set.hpp"
 #include "sparse_set.hpp"
 #include "entity.hpp"
 #include "entity.hpp"
@@ -61,7 +62,7 @@ class basic_runtime_view {
 
 
     using underlying_iterator_type = typename sparse_set<Entity>::iterator_type;
     using underlying_iterator_type = typename sparse_set<Entity>::iterator_type;
     using extent_type = typename sparse_set<Entity>::size_type;
     using extent_type = typename sparse_set<Entity>::size_type;
-    using traits_type = entt_traits<Entity>;
+    using traits_type = entt_traits<std::underlying_type_t<Entity>>;
 
 
     class iterator {
     class iterator {
         friend class basic_runtime_view<Entity>;
         friend class basic_runtime_view<Entity>;
@@ -80,7 +81,7 @@ class basic_runtime_view {
 
 
         bool valid() const ENTT_NOEXCEPT {
         bool valid() const ENTT_NOEXCEPT {
             const auto entt = *begin;
             const auto entt = *begin;
-            const auto sz = size_type(entt & traits_type::entity_mask);
+            const auto sz = size_type(to_integer(entt) & traits_type::entity_mask);
 
 
             return sz < extent && std::all_of(from, to, [entt](const auto *view) {
             return sz < extent && std::all_of(from, to, [entt](const auto *view) {
                 return view->has(entt);
                 return view->has(entt);

+ 13 - 11
src/entt/entity/snapshot.hpp

@@ -32,6 +32,7 @@ class basic_snapshot {
     friend class basic_registry<Entity>;
     friend class basic_registry<Entity>;
 
 
     using follow_fn_type = Entity(const basic_registry<Entity> &, const Entity);
     using follow_fn_type = Entity(const basic_registry<Entity> &, const Entity);
+    using traits_type = entt_traits<std::underlying_type_t<Entity>>;
 
 
     basic_snapshot(const basic_registry<Entity> *source, Entity init, follow_fn_type *fn) ENTT_NOEXCEPT
     basic_snapshot(const basic_registry<Entity> *source, Entity init, follow_fn_type *fn) ENTT_NOEXCEPT
         : reg{source},
         : reg{source},
@@ -41,7 +42,7 @@ class basic_snapshot {
 
 
     template<typename Component, typename Archive, typename It>
     template<typename Component, typename Archive, typename It>
     void get(Archive &archive, std::size_t sz, It first, It last) const {
     void get(Archive &archive, std::size_t sz, It first, It last) const {
-        archive(static_cast<Entity>(sz));
+        archive(typename traits_type::entity_type(sz));
 
 
         while(first != last) {
         while(first != last) {
             const auto entt = *(first++);
             const auto entt = *(first++);
@@ -88,7 +89,7 @@ public:
      */
      */
     template<typename Archive>
     template<typename Archive>
     const basic_snapshot & entities(Archive &archive) const {
     const basic_snapshot & entities(Archive &archive) const {
-        archive(static_cast<Entity>(reg->alive()));
+        archive(typename traits_type::entity_type(reg->alive()));
         reg->each([&archive](const auto entt) { archive(entt); });
         reg->each([&archive](const auto entt) { archive(entt); });
         return *this;
         return *this;
     }
     }
@@ -106,7 +107,7 @@ public:
     template<typename Archive>
     template<typename Archive>
     const basic_snapshot & destroyed(Archive &archive) const {
     const basic_snapshot & destroyed(Archive &archive) const {
         auto size = reg->size() - reg->alive();
         auto size = reg->size() - reg->alive();
-        archive(static_cast<Entity>(size));
+        archive(typename traits_type::entity_type(size));
 
 
         if(size) {
         if(size) {
             auto curr = seed;
             auto curr = seed;
@@ -138,7 +139,7 @@ public:
             const auto sz = reg->template size<Component...>();
             const auto sz = reg->template size<Component...>();
             const auto *entities = reg->template data<Component...>();
             const auto *entities = reg->template data<Component...>();
 
 
-            archive(static_cast<Entity>(sz));
+            archive(typename traits_type::entity_type(sz));
 
 
             for(std::remove_const_t<decltype(sz)> pos{}; pos < sz; ++pos) {
             for(std::remove_const_t<decltype(sz)> pos{}; pos < sz; ++pos) {
                 const auto entt = entities[pos];
                 const auto entt = entities[pos];
@@ -199,6 +200,7 @@ class basic_snapshot_loader {
     friend class basic_registry<Entity>;
     friend class basic_registry<Entity>;
 
 
     using force_fn_type = void(basic_registry<Entity> &, const Entity, const bool);
     using force_fn_type = void(basic_registry<Entity> &, const Entity, const bool);
+    using traits_type = entt_traits<std::underlying_type_t<Entity>>;
 
 
     basic_snapshot_loader(basic_registry<Entity> *source, force_fn_type *fn) ENTT_NOEXCEPT
     basic_snapshot_loader(basic_registry<Entity> *source, force_fn_type *fn) ENTT_NOEXCEPT
         : reg{source},
         : reg{source},
@@ -210,7 +212,7 @@ class basic_snapshot_loader {
 
 
     template<typename Archive>
     template<typename Archive>
     void assure(Archive &archive, bool destroyed) const {
     void assure(Archive &archive, bool destroyed) const {
-        Entity length{};
+        typename traits_type::entity_type length{};
         archive(length);
         archive(length);
 
 
         while(length--) {
         while(length--) {
@@ -222,7 +224,7 @@ class basic_snapshot_loader {
 
 
     template<typename Type, typename Archive, typename... Args>
     template<typename Type, typename Archive, typename... Args>
     void assign(Archive &archive, Args... args) const {
     void assign(Archive &archive, Args... args) const {
-        Entity length{};
+        typename traits_type::entity_type length{};
         archive(length);
         archive(length);
 
 
         while(length--) {
         while(length--) {
@@ -344,7 +346,7 @@ private:
  */
  */
 template<typename Entity>
 template<typename Entity>
 class basic_continuous_loader {
 class basic_continuous_loader {
-    using traits_type = entt_traits<Entity>;
+    using traits_type = entt_traits<std::underlying_type_t<Entity>>;
 
 
     void destroy(Entity entt) {
     void destroy(Entity entt) {
         const auto it = remloc.find(entt);
         const auto it = remloc.find(entt);
@@ -385,7 +387,7 @@ class basic_continuous_loader {
 
 
     template<typename Archive>
     template<typename Archive>
     void assure(Archive &archive, void(basic_continuous_loader:: *member)(Entity)) {
     void assure(Archive &archive, void(basic_continuous_loader:: *member)(Entity)) {
-        Entity length{};
+        typename traits_type::entity_type length{};
         archive(length);
         archive(length);
 
 
         while(length--) {
         while(length--) {
@@ -408,7 +410,7 @@ class basic_continuous_loader {
 
 
     template<typename Other, typename Archive, typename... Type, typename... Member>
     template<typename Other, typename Archive, typename... Type, typename... Member>
     void assign(Archive &archive, [[maybe_unused]] Member Type:: *... member) {
     void assign(Archive &archive, [[maybe_unused]] Member Type:: *... member) {
-        Entity length{};
+        typename traits_type::entity_type length{};
         archive(length);
         archive(length);
 
 
         while(length--) {
         while(length--) {
@@ -578,8 +580,8 @@ public:
     }
     }
 
 
 private:
 private:
-    std::unordered_map<Entity, std::pair<Entity, bool>> remloc;
-    basic_registry<Entity> *reg;
+    std::unordered_map<entity_type, std::pair<entity_type, bool>> remloc;
+    basic_registry<entity_type> *reg;
 };
 };
 
 
 
 

+ 7 - 5
src/entt/entity/sparse_set.hpp

@@ -8,8 +8,10 @@
 #include <vector>
 #include <vector>
 #include <memory>
 #include <memory>
 #include <cstddef>
 #include <cstddef>
+#include <type_traits>
 #include "../config/config.h"
 #include "../config/config.h"
 #include "entity.hpp"
 #include "entity.hpp"
+#include "fwd.hpp"
 
 
 
 
 namespace entt {
 namespace entt {
@@ -44,7 +46,7 @@ namespace entt {
  */
  */
 template<typename Entity>
 template<typename Entity>
 class sparse_set {
 class sparse_set {
-    using traits_type = entt_traits<Entity>;
+    using traits_type = entt_traits<std::underlying_type_t<Entity>>;
 
 
     static_assert(ENTT_PAGE_SIZE && ((ENTT_PAGE_SIZE & (ENTT_PAGE_SIZE - 1)) == 0));
     static_assert(ENTT_PAGE_SIZE && ((ENTT_PAGE_SIZE & (ENTT_PAGE_SIZE - 1)) == 0));
     static constexpr auto entt_per_page = ENTT_PAGE_SIZE / sizeof(typename traits_type::entity_type);
     static constexpr auto entt_per_page = ENTT_PAGE_SIZE / sizeof(typename traits_type::entity_type);
@@ -163,7 +165,7 @@ class sparse_set {
     }
     }
 
 
     auto index(const Entity entt) const ENTT_NOEXCEPT {
     auto index(const Entity entt) const ENTT_NOEXCEPT {
-        const auto identifier = entt & traits_type::entity_mask;
+        const auto identifier = to_integer(entt) & traits_type::entity_mask;
         const auto page = size_type(identifier / entt_per_page);
         const auto page = size_type(identifier / entt_per_page);
         const auto offset = size_type(identifier & (entt_per_page - 1));
         const auto offset = size_type(identifier & (entt_per_page - 1));
         return std::make_pair(page, offset);
         return std::make_pair(page, offset);
@@ -413,11 +415,11 @@ public:
      */
      */
     template<typename It>
     template<typename It>
     void batch(It first, It last) {
     void batch(It first, It last) {
-        std::for_each(first, last, [next = entity_type(direct.size()), this](const auto entt) mutable {
+        std::for_each(first, last, [next = direct.size(), this](const auto entt) mutable {
             ENTT_ASSERT(!has(entt));
             ENTT_ASSERT(!has(entt));
             auto [page, offset] = index(entt);
             auto [page, offset] = index(entt);
             assure(page);
             assure(page);
-            reverse[page][offset] = next++;
+            reverse[page][offset] = entity_type(next++);
         });
         });
 
 
         direct.insert(direct.end(), first, last);
         direct.insert(direct.end(), first, last);
@@ -438,7 +440,7 @@ public:
         ENTT_ASSERT(has(entt));
         ENTT_ASSERT(has(entt));
         auto [from_page, from_offset] = index(entt);
         auto [from_page, from_offset] = index(entt);
         auto [to_page, to_offset] = index(direct.back());
         auto [to_page, to_offset] = index(direct.back());
-        direct[size_type(reverse[from_page][from_offset])] = direct.back();
+        direct[size_type(reverse[from_page][from_offset])] = entity_type(direct.back());
         reverse[to_page][to_offset] = reverse[from_page][from_offset];
         reverse[to_page][to_offset] = reverse[from_page][from_offset];
         reverse[from_page][from_offset] = null;
         reverse[from_page][from_offset] = null;
         direct.pop_back();
         direct.pop_back();

+ 2 - 2
src/entt/entity/storage.hpp

@@ -49,7 +49,7 @@ namespace entt {
 template<typename Entity, typename Type, typename = std::void_t<>>
 template<typename Entity, typename Type, typename = std::void_t<>>
 class basic_storage: public sparse_set<Entity> {
 class basic_storage: public sparse_set<Entity> {
     using underlying_type = sparse_set<Entity>;
     using underlying_type = sparse_set<Entity>;
-    using traits_type = entt_traits<Entity>;
+    using traits_type = entt_traits<std::underlying_type_t<Entity>>;
 
 
     template<bool Const>
     template<bool Const>
     class iterator {
     class iterator {
@@ -530,8 +530,8 @@ private:
 /*! @copydoc basic_storage */
 /*! @copydoc basic_storage */
 template<typename Entity, typename Type>
 template<typename Entity, typename Type>
 class basic_storage<Entity, Type, std::enable_if_t<std::is_empty_v<Type>>>: public sparse_set<Entity> {
 class basic_storage<Entity, Type, std::enable_if_t<std::is_empty_v<Type>>>: public sparse_set<Entity> {
+    using traits_type = entt_traits<std::underlying_type_t<Entity>>;
     using underlying_type = sparse_set<Entity>;
     using underlying_type = sparse_set<Entity>;
-    using traits_type = entt_traits<Entity>;
 
 
     class iterator {
     class iterator {
         friend class basic_storage<Entity, Type>;
         friend class basic_storage<Entity, Type>;

+ 2 - 2
src/entt/entity/view.hpp

@@ -71,7 +71,7 @@ class basic_view {
 
 
     using underlying_iterator_type = typename sparse_set<Entity>::iterator_type;
     using underlying_iterator_type = typename sparse_set<Entity>::iterator_type;
     using unchecked_type = std::array<const sparse_set<Entity> *, (sizeof...(Component) - 1)>;
     using unchecked_type = std::array<const sparse_set<Entity> *, (sizeof...(Component) - 1)>;
-    using traits_type = entt_traits<Entity>;
+    using traits_type = entt_traits<std::underlying_type_t<Entity>>;
 
 
     class iterator {
     class iterator {
         friend class basic_view<Entity, Component...>;
         friend class basic_view<Entity, Component...>;
@@ -96,7 +96,7 @@ class basic_view {
 
 
         bool valid() const ENTT_NOEXCEPT {
         bool valid() const ENTT_NOEXCEPT {
             const auto entt = *begin;
             const auto entt = *begin;
-            const auto sz = size_type(entt& traits_type::entity_mask);
+            const auto sz = size_type(to_integer(entt) & traits_type::entity_mask);
 
 
             return sz < extent && std::all_of(unchecked.cbegin(), unchecked.cend(), [entt](const sparse_set<Entity> *view) {
             return sz < extent && std::all_of(unchecked.cbegin(), unchecked.cend(), [entt](const sparse_set<Entity> *view) {
                 return view->has(entt);
                 return view->has(entt);

+ 5 - 2
test/entt/entity/entity.cpp

@@ -1,15 +1,18 @@
 #include <functional>
 #include <functional>
+#include <type_traits>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <entt/entity/entity.hpp>
 #include <entt/entity/entity.hpp>
 #include <entt/entity/registry.hpp>
 #include <entt/entity/registry.hpp>
 
 
 TEST(Traits, Null) {
 TEST(Traits, Null) {
-    entt::registry registry{};
+    using traits_type = entt::entt_traits<std::underlying_type_t<entt::entity>>;
 
 
+    entt::registry registry{};
     const auto entity = registry.create();
     const auto entity = registry.create();
+
     registry.assign<int>(entity, 42);
     registry.assign<int>(entity, 42);
 
 
-    ASSERT_TRUE(~entt::entity{} == entt::null);
+    ASSERT_TRUE(entt::entity{~traits_type::entity_type{}} == entt::null);
 
 
     ASSERT_TRUE(entt::null == entt::null);
     ASSERT_TRUE(entt::null == entt::null);
     ASSERT_FALSE(entt::null != entt::null);
     ASSERT_FALSE(entt::null != entt::null);

+ 8 - 8
test/entt/entity/group.cpp

@@ -242,9 +242,9 @@ TEST(NonOwningGroup, ConstNonConstAndAllInBetween) {
 
 
     ASSERT_EQ(group.size(), decltype(group.size()){1});
     ASSERT_EQ(group.size(), decltype(group.size()){1});
 
 
-    ASSERT_TRUE((std::is_same_v<decltype(group.get<int>(0)), int &>));
-    ASSERT_TRUE((std::is_same_v<decltype(group.get<const char>(0)), const char &>));
-    ASSERT_TRUE((std::is_same_v<decltype(group.get<int, const char>(0)), std::tuple<int &, const char &>>));
+    ASSERT_TRUE((std::is_same_v<decltype(group.get<int>(entt::entity{0})), int &>));
+    ASSERT_TRUE((std::is_same_v<decltype(group.get<const char>(entt::entity{0})), const char &>));
+    ASSERT_TRUE((std::is_same_v<decltype(group.get<int, const char>(entt::entity{0})), std::tuple<int &, const char &>>));
     ASSERT_TRUE((std::is_same_v<decltype(group.raw<const char>()), const char *>));
     ASSERT_TRUE((std::is_same_v<decltype(group.raw<const char>()), const char *>));
     ASSERT_TRUE((std::is_same_v<decltype(group.raw<int>()), int *>));
     ASSERT_TRUE((std::is_same_v<decltype(group.raw<int>()), int *>));
 
 
@@ -761,11 +761,11 @@ TEST(OwningGroup, ConstNonConstAndAllInBetween) {
 
 
     ASSERT_EQ(group.size(), decltype(group.size()){1});
     ASSERT_EQ(group.size(), decltype(group.size()){1});
 
 
-    ASSERT_TRUE((std::is_same_v<decltype(group.get<int>(0)), int &>));
-    ASSERT_TRUE((std::is_same_v<decltype(group.get<const char>(0)), const char &>));
-    ASSERT_TRUE((std::is_same_v<decltype(group.get<double>(0)), double &>));
-    ASSERT_TRUE((std::is_same_v<decltype(group.get<const float>(0)), const float &>));
-    ASSERT_TRUE((std::is_same_v<decltype(group.get<int, const char, double, const float>(0)), std::tuple<int &, const char &, double &, const float &>>));
+    ASSERT_TRUE((std::is_same_v<decltype(group.get<int>(entt::entity{0})), int &>));
+    ASSERT_TRUE((std::is_same_v<decltype(group.get<const char>(entt::entity{0})), const char &>));
+    ASSERT_TRUE((std::is_same_v<decltype(group.get<double>(entt::entity{0})), double &>));
+    ASSERT_TRUE((std::is_same_v<decltype(group.get<const float>(entt::entity{0})), const float &>));
+    ASSERT_TRUE((std::is_same_v<decltype(group.get<int, const char, double, const float>(entt::entity{0})), std::tuple<int &, const char &, double &, const float &>>));
     ASSERT_TRUE((std::is_same_v<decltype(group.raw<const float>()), const float *>));
     ASSERT_TRUE((std::is_same_v<decltype(group.raw<const float>()), const float *>));
     ASSERT_TRUE((std::is_same_v<decltype(group.raw<double>()), double *>));
     ASSERT_TRUE((std::is_same_v<decltype(group.raw<double>()), double *>));
     ASSERT_TRUE((std::is_same_v<decltype(group.raw<const char>()), const char *>));
     ASSERT_TRUE((std::is_same_v<decltype(group.raw<const char>()), const char *>));

+ 1 - 1
test/entt/entity/registry.cpp

@@ -311,7 +311,7 @@ TEST(Registry, VersionOverflow) {
 
 
     ASSERT_EQ(registry.version(entity), entt::registry::version_type{});
     ASSERT_EQ(registry.version(entity), entt::registry::version_type{});
 
 
-    for(auto i = entt::entt_traits<entt::entity>::version_mask; i; --i) {
+    for(auto i = entt::entt_traits<std::underlying_type_t<entt::entity>>::version_mask; i; --i) {
         ASSERT_NE(registry.current(entity), registry.version(entity));
         ASSERT_NE(registry.current(entity), registry.version(entity));
         registry.destroy(registry.create());
         registry.destroy(registry.create());
     }
     }

+ 23 - 2
test/entt/entity/snapshot.cpp

@@ -1,6 +1,7 @@
 #include <tuple>
 #include <tuple>
 #include <queue>
 #include <queue>
 #include <vector>
 #include <vector>
+#include <type_traits>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <entt/entity/registry.hpp>
 #include <entt/entity/registry.hpp>
 #include <entt/entity/entity.hpp>
 #include <entt/entity/entity.hpp>
@@ -54,6 +55,8 @@ struct what_a_component {
 };
 };
 
 
 TEST(Snapshot, Dump) {
 TEST(Snapshot, Dump) {
+    using traits_type = entt::entt_traits<std::underlying_type_t<entt::entity>>;
+
     entt::registry registry;
     entt::registry registry;
 
 
     const auto e0 = registry.create();
     const auto e0 = registry.create();
@@ -74,6 +77,7 @@ TEST(Snapshot, Dump) {
     auto v1 = registry.current(e1);
     auto v1 = registry.current(e1);
 
 
     using storage_type = std::tuple<
     using storage_type = std::tuple<
+        std::queue<typename traits_type::entity_type>,
         std::queue<entt::entity>,
         std::queue<entt::entity>,
         std::queue<int>,
         std::queue<int>,
         std::queue<char>,
         std::queue<char>,
@@ -125,6 +129,8 @@ TEST(Snapshot, Dump) {
 }
 }
 
 
 TEST(Snapshot, Partial) {
 TEST(Snapshot, Partial) {
+    using traits_type = entt::entt_traits<std::underlying_type_t<entt::entity>>;
+
     entt::registry registry;
     entt::registry registry;
 
 
     const auto e0 = registry.create();
     const auto e0 = registry.create();
@@ -144,6 +150,7 @@ TEST(Snapshot, Partial) {
     auto v1 = registry.current(e1);
     auto v1 = registry.current(e1);
 
 
     using storage_type = std::tuple<
     using storage_type = std::tuple<
+        std::queue<typename traits_type::entity_type>,
         std::queue<entt::entity>,
         std::queue<entt::entity>,
         std::queue<int>,
         std::queue<int>,
         std::queue<char>,
         std::queue<char>,
@@ -206,6 +213,8 @@ TEST(Snapshot, Partial) {
 }
 }
 
 
 TEST(Snapshot, Iterator) {
 TEST(Snapshot, Iterator) {
+    using traits_type = entt::entt_traits<std::underlying_type_t<entt::entity>>;
+
     entt::registry registry;
     entt::registry registry;
 
 
     for(auto i = 0; i < 50; ++i) {
     for(auto i = 0; i < 50; ++i) {
@@ -218,6 +227,7 @@ TEST(Snapshot, Iterator) {
     }
     }
 
 
     using storage_type = std::tuple<
     using storage_type = std::tuple<
+        std::queue<typename traits_type::entity_type>,
         std::queue<entt::entity>,
         std::queue<entt::entity>,
         std::queue<another_component>
         std::queue<another_component>
     >;
     >;
@@ -236,11 +246,13 @@ TEST(Snapshot, Iterator) {
     ASSERT_EQ(registry.view<another_component>().size(), size);
     ASSERT_EQ(registry.view<another_component>().size(), size);
 
 
     registry.view<another_component>().each([](const auto entity, const auto &) {
     registry.view<another_component>().each([](const auto entity, const auto &) {
-        ASSERT_TRUE(entity % 2);
+        ASSERT_TRUE(entt::to_integer(entity) % 2);
     });
     });
 }
 }
 
 
 TEST(Snapshot, Continuous) {
 TEST(Snapshot, Continuous) {
+    using traits_type = entt::entt_traits<std::underlying_type_t<entt::entity>>;
+
     entt::registry src;
     entt::registry src;
     entt::registry dst;
     entt::registry dst;
 
 
@@ -250,6 +262,7 @@ TEST(Snapshot, Continuous) {
     entt::entity entity;
     entt::entity entity;
 
 
     using storage_type = std::tuple<
     using storage_type = std::tuple<
+        std::queue<typename traits_type::entity_type>,
         std::queue<entt::entity>,
         std::queue<entt::entity>,
         std::queue<another_component>,
         std::queue<another_component>,
         std::queue<what_a_component>,
         std::queue<what_a_component>,
@@ -429,12 +442,17 @@ TEST(Snapshot, Continuous) {
 }
 }
 
 
 TEST(Snapshot, MoreOnShrink) {
 TEST(Snapshot, MoreOnShrink) {
+    using traits_type = entt::entt_traits<std::underlying_type_t<entt::entity>>;
+
     entt::registry src;
     entt::registry src;
     entt::registry dst;
     entt::registry dst;
 
 
     entt::continuous_loader loader{dst};
     entt::continuous_loader loader{dst};
 
 
-    using storage_type = std::tuple<std::queue<entt::entity>>;
+    using storage_type = std::tuple<
+        std::queue<typename traits_type::entity_type>,
+        std::queue<entt::entity>
+    >;
 
 
     storage_type storage;
     storage_type storage;
     output_archive<storage_type> output{storage};
     output_archive<storage_type> output{storage};
@@ -452,12 +470,15 @@ TEST(Snapshot, MoreOnShrink) {
 }
 }
 
 
 TEST(Snapshot, SyncDataMembers) {
 TEST(Snapshot, SyncDataMembers) {
+    using traits_type = entt::entt_traits<std::underlying_type_t<entt::entity>>;
+
     entt::registry src;
     entt::registry src;
     entt::registry dst;
     entt::registry dst;
 
 
     entt::continuous_loader loader{dst};
     entt::continuous_loader loader{dst};
 
 
     using storage_type = std::tuple<
     using storage_type = std::tuple<
+        std::queue<typename traits_type::entity_type>,
         std::queue<entt::entity>,
         std::queue<entt::entity>,
         std::queue<what_a_component>
         std::queue<what_a_component>
     >;
     >;

+ 205 - 204
test/entt/entity/sparse_set.cpp

@@ -4,12 +4,13 @@
 #include <type_traits>
 #include <type_traits>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <entt/entity/sparse_set.hpp>
 #include <entt/entity/sparse_set.hpp>
+#include <entt/entity/fwd.hpp>
 
 
 struct empty_type {};
 struct empty_type {};
 struct boxed_int { int value; };
 struct boxed_int { int value; };
 
 
 TEST(SparseSet, Functionalities) {
 TEST(SparseSet, Functionalities) {
-    entt::sparse_set<std::uint64_t> set;
+    entt::sparse_set<entt::entity> set;
 
 
     set.reserve(42);
     set.reserve(42);
 
 
@@ -18,54 +19,54 @@ TEST(SparseSet, Functionalities) {
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_EQ(set.begin(), set.end());
     ASSERT_EQ(set.begin(), set.end());
-    ASSERT_FALSE(set.has(0));
-    ASSERT_FALSE(set.has(42));
+    ASSERT_FALSE(set.has(entt::entity{0}));
+    ASSERT_FALSE(set.has(entt::entity{42}));
 
 
-    set.construct(42);
+    set.construct(entt::entity{42});
 
 
-    ASSERT_EQ(set.get(42), 0u);
+    ASSERT_EQ(set.get(entt::entity{42}), 0u);
 
 
     ASSERT_FALSE(set.empty());
     ASSERT_FALSE(set.empty());
     ASSERT_EQ(set.size(), 1u);
     ASSERT_EQ(set.size(), 1u);
     ASSERT_NE(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_NE(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_NE(set.begin(), set.end());
     ASSERT_NE(set.begin(), set.end());
-    ASSERT_FALSE(set.has(0));
-    ASSERT_TRUE(set.has(42));
-    ASSERT_EQ(set.get(42), 0u);
+    ASSERT_FALSE(set.has(entt::entity{0}));
+    ASSERT_TRUE(set.has(entt::entity{42}));
+    ASSERT_EQ(set.get(entt::entity{42}), 0u);
 
 
-    set.destroy(42);
+    set.destroy(entt::entity{42});
 
 
     ASSERT_TRUE(set.empty());
     ASSERT_TRUE(set.empty());
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_EQ(set.begin(), set.end());
     ASSERT_EQ(set.begin(), set.end());
-    ASSERT_FALSE(set.has(0));
-    ASSERT_FALSE(set.has(42));
+    ASSERT_FALSE(set.has(entt::entity{0}));
+    ASSERT_FALSE(set.has(entt::entity{42}));
 
 
-    set.construct(42);
+    set.construct(entt::entity{42});
 
 
     ASSERT_FALSE(set.empty());
     ASSERT_FALSE(set.empty());
-    ASSERT_EQ(set.get(42), 0u);
+    ASSERT_EQ(set.get(entt::entity{42}), 0u);
 
 
     ASSERT_TRUE(std::is_move_constructible_v<decltype(set)>);
     ASSERT_TRUE(std::is_move_constructible_v<decltype(set)>);
     ASSERT_TRUE(std::is_move_assignable_v<decltype(set)>);
     ASSERT_TRUE(std::is_move_assignable_v<decltype(set)>);
 
 
-    entt::sparse_set<std::uint64_t> cpy{set};
+    entt::sparse_set<entt::entity> cpy{set};
     set = cpy;
     set = cpy;
 
 
     ASSERT_FALSE(set.empty());
     ASSERT_FALSE(set.empty());
     ASSERT_FALSE(cpy.empty());
     ASSERT_FALSE(cpy.empty());
-    ASSERT_EQ(set.get(42), 0u);
-    ASSERT_EQ(cpy.get(42), 0u);
+    ASSERT_EQ(set.get(entt::entity{42}), 0u);
+    ASSERT_EQ(cpy.get(entt::entity{42}), 0u);
 
 
-    entt::sparse_set<std::uint64_t> other{std::move(set)};
+    entt::sparse_set<entt::entity> other{std::move(set)};
 
 
     set = std::move(other);
     set = std::move(other);
     other = std::move(set);
     other = std::move(set);
 
 
     ASSERT_TRUE(set.empty());
     ASSERT_TRUE(set.empty());
     ASSERT_FALSE(other.empty());
     ASSERT_FALSE(other.empty());
-    ASSERT_EQ(other.get(42), 0u);
+    ASSERT_EQ(other.get(entt::entity{42}), 0u);
 
 
     other.reset();
     other.reset();
 
 
@@ -73,40 +74,40 @@ TEST(SparseSet, Functionalities) {
     ASSERT_EQ(other.size(), 0u);
     ASSERT_EQ(other.size(), 0u);
     ASSERT_EQ(std::as_const(other).begin(), std::as_const(other).end());
     ASSERT_EQ(std::as_const(other).begin(), std::as_const(other).end());
     ASSERT_EQ(other.begin(), other.end());
     ASSERT_EQ(other.begin(), other.end());
-    ASSERT_FALSE(other.has(0));
-    ASSERT_FALSE(other.has(42));
+    ASSERT_FALSE(other.has(entt::entity{0}));
+    ASSERT_FALSE(other.has(entt::entity{42}));
 }
 }
 
 
 TEST(SparseSet, Pagination) {
 TEST(SparseSet, Pagination) {
-    entt::sparse_set<std::uint64_t> set;
-    constexpr auto entt_per_page = ENTT_PAGE_SIZE / sizeof(std::uint64_t);
+    entt::sparse_set<entt::entity> set;
+    constexpr auto entt_per_page = ENTT_PAGE_SIZE / sizeof(std::underlying_type_t<entt::entity>);
 
 
     ASSERT_EQ(set.extent(), 0);
     ASSERT_EQ(set.extent(), 0);
 
 
-    set.construct(entt_per_page-1);
+    set.construct(entt::entity{entt_per_page-1});
 
 
     ASSERT_EQ(set.extent(), entt_per_page);
     ASSERT_EQ(set.extent(), entt_per_page);
-    ASSERT_TRUE(set.has(entt_per_page-1));
+    ASSERT_TRUE(set.has(entt::entity{entt_per_page-1}));
 
 
-    set.construct(entt_per_page);
+    set.construct(entt::entity{entt_per_page});
 
 
     ASSERT_EQ(set.extent(), 2 * entt_per_page);
     ASSERT_EQ(set.extent(), 2 * entt_per_page);
-    ASSERT_TRUE(set.has(entt_per_page-1));
-    ASSERT_TRUE(set.has(entt_per_page));
-    ASSERT_FALSE(set.has(entt_per_page+1));
+    ASSERT_TRUE(set.has(entt::entity{entt_per_page-1}));
+    ASSERT_TRUE(set.has(entt::entity{entt_per_page}));
+    ASSERT_FALSE(set.has(entt::entity{entt_per_page+1}));
 
 
-    set.destroy(entt_per_page-1);
+    set.destroy(entt::entity{entt_per_page-1});
 
 
     ASSERT_EQ(set.extent(), 2 * entt_per_page);
     ASSERT_EQ(set.extent(), 2 * entt_per_page);
-    ASSERT_FALSE(set.has(entt_per_page-1));
-    ASSERT_TRUE(set.has(entt_per_page));
+    ASSERT_FALSE(set.has(entt::entity{entt_per_page-1}));
+    ASSERT_TRUE(set.has(entt::entity{entt_per_page}));
 
 
     set.shrink_to_fit();
     set.shrink_to_fit();
-    set.destroy(entt_per_page);
+    set.destroy(entt::entity{entt_per_page});
 
 
     ASSERT_EQ(set.extent(), 2 * entt_per_page);
     ASSERT_EQ(set.extent(), 2 * entt_per_page);
-    ASSERT_FALSE(set.has(entt_per_page-1));
-    ASSERT_FALSE(set.has(entt_per_page));
+    ASSERT_FALSE(set.has(entt::entity{entt_per_page-1}));
+    ASSERT_FALSE(set.has(entt::entity{entt_per_page}));
 
 
     set.shrink_to_fit();
     set.shrink_to_fit();
 
 
@@ -114,36 +115,36 @@ TEST(SparseSet, Pagination) {
 }
 }
 
 
 TEST(SparseSet, BatchAdd) {
 TEST(SparseSet, BatchAdd) {
-    entt::sparse_set<std::uint64_t> set;
-    entt::sparse_set<std::uint64_t>::entity_type entities[2];
+    entt::sparse_set<entt::entity> set;
+    entt::sparse_set<entt::entity>::entity_type entities[2];
 
 
-    entities[0] = 3;
-    entities[1] = 42;
+    entities[0] = entt::entity{3};
+    entities[1] = entt::entity{42};
 
 
-    set.construct(12);
+    set.construct(entt::entity{12});
     set.batch(std::begin(entities), std::end(entities));
     set.batch(std::begin(entities), std::end(entities));
-    set.construct(24);
+    set.construct(entt::entity{24});
 
 
     ASSERT_TRUE(set.has(entities[0]));
     ASSERT_TRUE(set.has(entities[0]));
     ASSERT_TRUE(set.has(entities[1]));
     ASSERT_TRUE(set.has(entities[1]));
-    ASSERT_FALSE(set.has(0));
-    ASSERT_FALSE(set.has(9));
-    ASSERT_TRUE(set.has(12));
-    ASSERT_TRUE(set.has(24));
+    ASSERT_FALSE(set.has(entt::entity{0}));
+    ASSERT_FALSE(set.has(entt::entity{9}));
+    ASSERT_TRUE(set.has(entt::entity{12}));
+    ASSERT_TRUE(set.has(entt::entity{24}));
 
 
     ASSERT_FALSE(set.empty());
     ASSERT_FALSE(set.empty());
     ASSERT_EQ(set.size(), 4u);
     ASSERT_EQ(set.size(), 4u);
-    ASSERT_EQ(set.get(12), 0u);
+    ASSERT_EQ(set.get(entt::entity{12}), 0u);
     ASSERT_EQ(set.get(entities[0]), 1u);
     ASSERT_EQ(set.get(entities[0]), 1u);
     ASSERT_EQ(set.get(entities[1]), 2u);
     ASSERT_EQ(set.get(entities[1]), 2u);
-    ASSERT_EQ(set.get(24), 3u);
+    ASSERT_EQ(set.get(entt::entity{24}), 3u);
 }
 }
 
 
 TEST(SparseSet, Iterator) {
 TEST(SparseSet, Iterator) {
-    using iterator_type = typename entt::sparse_set<std::uint64_t>::iterator_type;
+    using iterator_type = typename entt::sparse_set<entt::entity>::iterator_type;
 
 
-    entt::sparse_set<std::uint64_t> set;
-    set.construct(3);
+    entt::sparse_set<entt::entity> set;
+    set.construct(entt::entity{3});
 
 
     iterator_type end{set.begin()};
     iterator_type end{set.begin()};
     iterator_type begin{};
     iterator_type begin{};
@@ -180,216 +181,216 @@ TEST(SparseSet, Iterator) {
     ASSERT_GT(end, begin);
     ASSERT_GT(end, begin);
     ASSERT_GE(end, set.end());
     ASSERT_GE(end, set.end());
 
 
-    ASSERT_EQ(*begin, 3);
-    ASSERT_EQ(*begin.operator->(), 3);
+    ASSERT_EQ(*begin, entt::entity{3});
+    ASSERT_EQ(*begin.operator->(), entt::entity{3});
 }
 }
 
 
 TEST(SparseSet, Find) {
 TEST(SparseSet, Find) {
-    entt::sparse_set<std::uint64_t> set;
-    set.construct(3);
-    set.construct(42);
-    set.construct(99);
+    entt::sparse_set<entt::entity> set;
+    set.construct(entt::entity{3});
+    set.construct(entt::entity{42});
+    set.construct(entt::entity{99});
 
 
-    ASSERT_NE(set.find(3), set.end());
-    ASSERT_NE(set.find(42), set.end());
-    ASSERT_NE(set.find(99), set.end());
-    ASSERT_EQ(set.find(0), set.end());
+    ASSERT_NE(set.find(entt::entity{3}), set.end());
+    ASSERT_NE(set.find(entt::entity{42}), set.end());
+    ASSERT_NE(set.find(entt::entity{99}), set.end());
+    ASSERT_EQ(set.find(entt::entity{0}), set.end());
 
 
-    auto it = set.find(99);
+    auto it = set.find(entt::entity{99});
 
 
-    ASSERT_EQ(*it, 99);
-    ASSERT_EQ(*(++it), 42);
-    ASSERT_EQ(*(++it), 3);
+    ASSERT_EQ(*it, entt::entity{99});
+    ASSERT_EQ(*(++it), entt::entity{42});
+    ASSERT_EQ(*(++it), entt::entity{3});
     ASSERT_EQ(++it, set.end());
     ASSERT_EQ(++it, set.end());
-    ASSERT_EQ(++set.find(3), set.end());
+    ASSERT_EQ(++set.find(entt::entity{3}), set.end());
 }
 }
 
 
 TEST(SparseSet, Data) {
 TEST(SparseSet, Data) {
-    entt::sparse_set<std::uint64_t> set;
+    entt::sparse_set<entt::entity> set;
 
 
-    set.construct(3);
-    set.construct(12);
-    set.construct(42);
+    set.construct(entt::entity{3});
+    set.construct(entt::entity{12});
+    set.construct(entt::entity{42});
 
 
-    ASSERT_EQ(set.get(3), 0u);
-    ASSERT_EQ(set.get(12), 1u);
-    ASSERT_EQ(set.get(42), 2u);
+    ASSERT_EQ(set.get(entt::entity{3}), 0u);
+    ASSERT_EQ(set.get(entt::entity{12}), 1u);
+    ASSERT_EQ(set.get(entt::entity{42}), 2u);
 
 
-    ASSERT_EQ(*(set.data() + 0u), 3u);
-    ASSERT_EQ(*(set.data() + 1u), 12u);
-    ASSERT_EQ(*(set.data() + 2u), 42u);
+    ASSERT_EQ(*(set.data() + 0u), entt::entity{3});
+    ASSERT_EQ(*(set.data() + 1u), entt::entity{12});
+    ASSERT_EQ(*(set.data() + 2u), entt::entity{42});
 }
 }
 
 
 TEST(SparseSet, RespectDisjoint) {
 TEST(SparseSet, RespectDisjoint) {
-    entt::sparse_set<std::uint64_t> lhs;
-    entt::sparse_set<std::uint64_t> rhs;
+    entt::sparse_set<entt::entity> lhs;
+    entt::sparse_set<entt::entity> rhs;
 
 
-    lhs.construct(3);
-    lhs.construct(12);
-    lhs.construct(42);
+    lhs.construct(entt::entity{3});
+    lhs.construct(entt::entity{12});
+    lhs.construct(entt::entity{42});
 
 
-    ASSERT_EQ(lhs.get(3), 0u);
-    ASSERT_EQ(lhs.get(12), 1u);
-    ASSERT_EQ(lhs.get(42), 2u);
+    ASSERT_EQ(lhs.get(entt::entity{3}), 0u);
+    ASSERT_EQ(lhs.get(entt::entity{12}), 1u);
+    ASSERT_EQ(lhs.get(entt::entity{42}), 2u);
 
 
     lhs.respect(rhs);
     lhs.respect(rhs);
 
 
-    ASSERT_EQ(std::as_const(lhs).get(3), 0u);
-    ASSERT_EQ(std::as_const(lhs).get(12), 1u);
-    ASSERT_EQ(std::as_const(lhs).get(42), 2u);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{3}), 0u);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{12}), 1u);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{42}), 2u);
 }
 }
 
 
 TEST(SparseSet, RespectOverlap) {
 TEST(SparseSet, RespectOverlap) {
-    entt::sparse_set<std::uint64_t> lhs;
-    entt::sparse_set<std::uint64_t> rhs;
+    entt::sparse_set<entt::entity> lhs;
+    entt::sparse_set<entt::entity> rhs;
 
 
-    lhs.construct(3);
-    lhs.construct(12);
-    lhs.construct(42);
+    lhs.construct(entt::entity{3});
+    lhs.construct(entt::entity{12});
+    lhs.construct(entt::entity{42});
 
 
-    rhs.construct(12);
+    rhs.construct(entt::entity{12});
 
 
-    ASSERT_EQ(lhs.get(3), 0u);
-    ASSERT_EQ(lhs.get(12), 1u);
-    ASSERT_EQ(lhs.get(42), 2u);
+    ASSERT_EQ(lhs.get(entt::entity{3}), 0u);
+    ASSERT_EQ(lhs.get(entt::entity{12}), 1u);
+    ASSERT_EQ(lhs.get(entt::entity{42}), 2u);
 
 
     lhs.respect(rhs);
     lhs.respect(rhs);
 
 
-    ASSERT_EQ(std::as_const(lhs).get(3), 0u);
-    ASSERT_EQ(std::as_const(lhs).get(12), 2u);
-    ASSERT_EQ(std::as_const(lhs).get(42), 1u);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{3}), 0u);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{12}), 2u);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{42}), 1u);
 }
 }
 
 
 TEST(SparseSet, RespectOrdered) {
 TEST(SparseSet, RespectOrdered) {
-    entt::sparse_set<std::uint64_t> lhs;
-    entt::sparse_set<std::uint64_t> rhs;
-
-    lhs.construct(1);
-    lhs.construct(2);
-    lhs.construct(3);
-    lhs.construct(4);
-    lhs.construct(5);
-
-    ASSERT_EQ(lhs.get(1), 0u);
-    ASSERT_EQ(lhs.get(2), 1u);
-    ASSERT_EQ(lhs.get(3), 2u);
-    ASSERT_EQ(lhs.get(4), 3u);
-    ASSERT_EQ(lhs.get(5), 4u);
-
-    rhs.construct(6);
-    rhs.construct(1);
-    rhs.construct(2);
-    rhs.construct(3);
-    rhs.construct(4);
-    rhs.construct(5);
-
-    ASSERT_EQ(rhs.get(6), 0u);
-    ASSERT_EQ(rhs.get(1), 1u);
-    ASSERT_EQ(rhs.get(2), 2u);
-    ASSERT_EQ(rhs.get(3), 3u);
-    ASSERT_EQ(rhs.get(4), 4u);
-    ASSERT_EQ(rhs.get(5), 5u);
+    entt::sparse_set<entt::entity> lhs;
+    entt::sparse_set<entt::entity> rhs;
+
+    lhs.construct(entt::entity{1});
+    lhs.construct(entt::entity{2});
+    lhs.construct(entt::entity{3});
+    lhs.construct(entt::entity{4});
+    lhs.construct(entt::entity{5});
+
+    ASSERT_EQ(lhs.get(entt::entity{1}), 0u);
+    ASSERT_EQ(lhs.get(entt::entity{2}), 1u);
+    ASSERT_EQ(lhs.get(entt::entity{3}), 2u);
+    ASSERT_EQ(lhs.get(entt::entity{4}), 3u);
+    ASSERT_EQ(lhs.get(entt::entity{5}), 4u);
+
+    rhs.construct(entt::entity{6});
+    rhs.construct(entt::entity{1});
+    rhs.construct(entt::entity{2});
+    rhs.construct(entt::entity{3});
+    rhs.construct(entt::entity{4});
+    rhs.construct(entt::entity{5});
+
+    ASSERT_EQ(rhs.get(entt::entity{6}), 0u);
+    ASSERT_EQ(rhs.get(entt::entity{1}), 1u);
+    ASSERT_EQ(rhs.get(entt::entity{2}), 2u);
+    ASSERT_EQ(rhs.get(entt::entity{3}), 3u);
+    ASSERT_EQ(rhs.get(entt::entity{4}), 4u);
+    ASSERT_EQ(rhs.get(entt::entity{5}), 5u);
 
 
     rhs.respect(lhs);
     rhs.respect(lhs);
 
 
-    ASSERT_EQ(rhs.get(6), 0u);
-    ASSERT_EQ(rhs.get(1), 1u);
-    ASSERT_EQ(rhs.get(2), 2u);
-    ASSERT_EQ(rhs.get(3), 3u);
-    ASSERT_EQ(rhs.get(4), 4u);
-    ASSERT_EQ(rhs.get(5), 5u);
+    ASSERT_EQ(rhs.get(entt::entity{6}), 0u);
+    ASSERT_EQ(rhs.get(entt::entity{1}), 1u);
+    ASSERT_EQ(rhs.get(entt::entity{2}), 2u);
+    ASSERT_EQ(rhs.get(entt::entity{3}), 3u);
+    ASSERT_EQ(rhs.get(entt::entity{4}), 4u);
+    ASSERT_EQ(rhs.get(entt::entity{5}), 5u);
 }
 }
 
 
 TEST(SparseSet, RespectReverse) {
 TEST(SparseSet, RespectReverse) {
-    entt::sparse_set<std::uint64_t> lhs;
-    entt::sparse_set<std::uint64_t> rhs;
-
-    lhs.construct(1);
-    lhs.construct(2);
-    lhs.construct(3);
-    lhs.construct(4);
-    lhs.construct(5);
-
-    ASSERT_EQ(lhs.get(1), 0u);
-    ASSERT_EQ(lhs.get(2), 1u);
-    ASSERT_EQ(lhs.get(3), 2u);
-    ASSERT_EQ(lhs.get(4), 3u);
-    ASSERT_EQ(lhs.get(5), 4u);
-
-    rhs.construct(5);
-    rhs.construct(4);
-    rhs.construct(3);
-    rhs.construct(2);
-    rhs.construct(1);
-    rhs.construct(6);
-
-    ASSERT_EQ(rhs.get(5), 0u);
-    ASSERT_EQ(rhs.get(4), 1u);
-    ASSERT_EQ(rhs.get(3), 2u);
-    ASSERT_EQ(rhs.get(2), 3u);
-    ASSERT_EQ(rhs.get(1), 4u);
-    ASSERT_EQ(rhs.get(6), 5u);
+    entt::sparse_set<entt::entity> lhs;
+    entt::sparse_set<entt::entity> rhs;
+
+    lhs.construct(entt::entity{1});
+    lhs.construct(entt::entity{2});
+    lhs.construct(entt::entity{3});
+    lhs.construct(entt::entity{4});
+    lhs.construct(entt::entity{5});
+
+    ASSERT_EQ(lhs.get(entt::entity{1}), 0u);
+    ASSERT_EQ(lhs.get(entt::entity{2}), 1u);
+    ASSERT_EQ(lhs.get(entt::entity{3}), 2u);
+    ASSERT_EQ(lhs.get(entt::entity{4}), 3u);
+    ASSERT_EQ(lhs.get(entt::entity{5}), 4u);
+
+    rhs.construct(entt::entity{5});
+    rhs.construct(entt::entity{4});
+    rhs.construct(entt::entity{3});
+    rhs.construct(entt::entity{2});
+    rhs.construct(entt::entity{1});
+    rhs.construct(entt::entity{6});
+
+    ASSERT_EQ(rhs.get(entt::entity{5}), 0u);
+    ASSERT_EQ(rhs.get(entt::entity{4}), 1u);
+    ASSERT_EQ(rhs.get(entt::entity{3}), 2u);
+    ASSERT_EQ(rhs.get(entt::entity{2}), 3u);
+    ASSERT_EQ(rhs.get(entt::entity{1}), 4u);
+    ASSERT_EQ(rhs.get(entt::entity{6}), 5u);
 
 
     rhs.respect(lhs);
     rhs.respect(lhs);
 
 
-    ASSERT_EQ(rhs.get(6), 0u);
-    ASSERT_EQ(rhs.get(1), 1u);
-    ASSERT_EQ(rhs.get(2), 2u);
-    ASSERT_EQ(rhs.get(3), 3u);
-    ASSERT_EQ(rhs.get(4), 4u);
-    ASSERT_EQ(rhs.get(5), 5u);
+    ASSERT_EQ(rhs.get(entt::entity{6}), 0u);
+    ASSERT_EQ(rhs.get(entt::entity{1}), 1u);
+    ASSERT_EQ(rhs.get(entt::entity{2}), 2u);
+    ASSERT_EQ(rhs.get(entt::entity{3}), 3u);
+    ASSERT_EQ(rhs.get(entt::entity{4}), 4u);
+    ASSERT_EQ(rhs.get(entt::entity{5}), 5u);
 }
 }
 
 
 TEST(SparseSet, RespectUnordered) {
 TEST(SparseSet, RespectUnordered) {
-    entt::sparse_set<std::uint64_t> lhs;
-    entt::sparse_set<std::uint64_t> rhs;
-
-    lhs.construct(1);
-    lhs.construct(2);
-    lhs.construct(3);
-    lhs.construct(4);
-    lhs.construct(5);
-
-    ASSERT_EQ(lhs.get(1), 0u);
-    ASSERT_EQ(lhs.get(2), 1u);
-    ASSERT_EQ(lhs.get(3), 2u);
-    ASSERT_EQ(lhs.get(4), 3u);
-    ASSERT_EQ(lhs.get(5), 4u);
-
-    rhs.construct(3);
-    rhs.construct(2);
-    rhs.construct(6);
-    rhs.construct(1);
-    rhs.construct(4);
-    rhs.construct(5);
-
-    ASSERT_EQ(rhs.get(3), 0u);
-    ASSERT_EQ(rhs.get(2), 1u);
-    ASSERT_EQ(rhs.get(6), 2u);
-    ASSERT_EQ(rhs.get(1), 3u);
-    ASSERT_EQ(rhs.get(4), 4u);
-    ASSERT_EQ(rhs.get(5), 5u);
+    entt::sparse_set<entt::entity> lhs;
+    entt::sparse_set<entt::entity> rhs;
+
+    lhs.construct(entt::entity{1});
+    lhs.construct(entt::entity{2});
+    lhs.construct(entt::entity{3});
+    lhs.construct(entt::entity{4});
+    lhs.construct(entt::entity{5});
+
+    ASSERT_EQ(lhs.get(entt::entity{1}), 0u);
+    ASSERT_EQ(lhs.get(entt::entity{2}), 1u);
+    ASSERT_EQ(lhs.get(entt::entity{3}), 2u);
+    ASSERT_EQ(lhs.get(entt::entity{4}), 3u);
+    ASSERT_EQ(lhs.get(entt::entity{5}), 4u);
+
+    rhs.construct(entt::entity{3});
+    rhs.construct(entt::entity{2});
+    rhs.construct(entt::entity{6});
+    rhs.construct(entt::entity{1});
+    rhs.construct(entt::entity{4});
+    rhs.construct(entt::entity{5});
+
+    ASSERT_EQ(rhs.get(entt::entity{3}), 0u);
+    ASSERT_EQ(rhs.get(entt::entity{2}), 1u);
+    ASSERT_EQ(rhs.get(entt::entity{6}), 2u);
+    ASSERT_EQ(rhs.get(entt::entity{1}), 3u);
+    ASSERT_EQ(rhs.get(entt::entity{4}), 4u);
+    ASSERT_EQ(rhs.get(entt::entity{5}), 5u);
 
 
     rhs.respect(lhs);
     rhs.respect(lhs);
 
 
-    ASSERT_EQ(rhs.get(6), 0u);
-    ASSERT_EQ(rhs.get(1), 1u);
-    ASSERT_EQ(rhs.get(2), 2u);
-    ASSERT_EQ(rhs.get(3), 3u);
-    ASSERT_EQ(rhs.get(4), 4u);
-    ASSERT_EQ(rhs.get(5), 5u);
+    ASSERT_EQ(rhs.get(entt::entity{6}), 0u);
+    ASSERT_EQ(rhs.get(entt::entity{1}), 1u);
+    ASSERT_EQ(rhs.get(entt::entity{2}), 2u);
+    ASSERT_EQ(rhs.get(entt::entity{3}), 3u);
+    ASSERT_EQ(rhs.get(entt::entity{4}), 4u);
+    ASSERT_EQ(rhs.get(entt::entity{5}), 5u);
 }
 }
 
 
 TEST(SparseSet, CanModifyDuringIteration) {
 TEST(SparseSet, CanModifyDuringIteration) {
-    entt::sparse_set<std::uint64_t> set;
-    set.construct(0);
+    entt::sparse_set<entt::entity> set;
+    set.construct(entt::entity{0});
 
 
-    ASSERT_EQ(set.capacity(), entt::sparse_set<std::uint64_t>::size_type{1});
+    ASSERT_EQ(set.capacity(), entt::sparse_set<entt::entity>::size_type{1});
 
 
     const auto it = set.begin();
     const auto it = set.begin();
-    set.reserve(entt::sparse_set<std::uint64_t>::size_type{2});
+    set.reserve(entt::sparse_set<entt::entity>::size_type{2});
 
 
-    ASSERT_EQ(set.capacity(), entt::sparse_set<std::uint64_t>::size_type{2});
+    ASSERT_EQ(set.capacity(), entt::sparse_set<entt::entity>::size_type{2});
 
 
     // this should crash with asan enabled if we break the constraint
     // this should crash with asan enabled if we break the constraint
     const auto entity = *it;
     const auto entity = *it;

+ 271 - 270
test/entt/entity/storage.cpp

@@ -6,6 +6,7 @@
 #include <unordered_set>
 #include <unordered_set>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <entt/entity/storage.hpp>
 #include <entt/entity/storage.hpp>
+#include <entt/entity/fwd.hpp>
 
 
 struct empty_type {};
 struct empty_type {};
 struct boxed_int { int value; };
 struct boxed_int { int value; };
@@ -20,7 +21,7 @@ struct throwing_component {
 };
 };
 
 
 TEST(Storage, Functionalities) {
 TEST(Storage, Functionalities) {
-    entt::storage<std::uint64_t, int> set;
+    entt::storage<entt::entity, int> set;
 
 
     set.reserve(42);
     set.reserve(42);
 
 
@@ -29,35 +30,35 @@ TEST(Storage, Functionalities) {
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_EQ(set.begin(), set.end());
     ASSERT_EQ(set.begin(), set.end());
-    ASSERT_FALSE(set.has(0));
-    ASSERT_FALSE(set.has(41));
+    ASSERT_FALSE(set.has(entt::entity{0}));
+    ASSERT_FALSE(set.has(entt::entity{41}));
 
 
-    set.construct(41, 3);
+    set.construct(entt::entity{41}, 3);
 
 
     ASSERT_FALSE(set.empty());
     ASSERT_FALSE(set.empty());
     ASSERT_EQ(set.size(), 1u);
     ASSERT_EQ(set.size(), 1u);
     ASSERT_NE(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_NE(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_NE(set.begin(), set.end());
     ASSERT_NE(set.begin(), set.end());
-    ASSERT_FALSE(set.has(0));
-    ASSERT_TRUE(set.has(41));
-    ASSERT_EQ(set.get(41), 3);
-    ASSERT_EQ(*set.try_get(41), 3);
-    ASSERT_EQ(set.try_get(99), nullptr);
+    ASSERT_FALSE(set.has(entt::entity{0}));
+    ASSERT_TRUE(set.has(entt::entity{41}));
+    ASSERT_EQ(set.get(entt::entity{41}), 3);
+    ASSERT_EQ(*set.try_get(entt::entity{41}), 3);
+    ASSERT_EQ(set.try_get(entt::entity{99}), nullptr);
 
 
-    set.destroy(41);
+    set.destroy(entt::entity{41});
 
 
     ASSERT_TRUE(set.empty());
     ASSERT_TRUE(set.empty());
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_EQ(set.begin(), set.end());
     ASSERT_EQ(set.begin(), set.end());
-    ASSERT_FALSE(set.has(0));
-    ASSERT_FALSE(set.has(41));
+    ASSERT_FALSE(set.has(entt::entity{0}));
+    ASSERT_FALSE(set.has(entt::entity{41}));
 
 
-    set.construct(41, 12);
+    set.construct(entt::entity{41}, 12);
 
 
-    ASSERT_EQ(set.get(41), 12);
-    ASSERT_EQ(*set.try_get(41), 12);
-    ASSERT_EQ(set.try_get(99), nullptr);
+    ASSERT_EQ(set.get(entt::entity{41}), 12);
+    ASSERT_EQ(*set.try_get(entt::entity{41}), 12);
+    ASSERT_EQ(set.try_get(entt::entity{99}), nullptr);
 
 
     set.reset();
     set.reset();
 
 
@@ -65,8 +66,8 @@ TEST(Storage, Functionalities) {
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
     ASSERT_EQ(set.begin(), set.end());
     ASSERT_EQ(set.begin(), set.end());
-    ASSERT_FALSE(set.has(0));
-    ASSERT_FALSE(set.has(41));
+    ASSERT_FALSE(set.has(entt::entity{0}));
+    ASSERT_FALSE(set.has(entt::entity{41}));
 
 
     ASSERT_EQ(set.capacity(), 42);
     ASSERT_EQ(set.capacity(), 42);
 
 
@@ -74,50 +75,50 @@ TEST(Storage, Functionalities) {
 
 
     ASSERT_EQ(set.capacity(), 0);
     ASSERT_EQ(set.capacity(), 0);
 
 
-    (void)entt::storage<std::uint64_t, int>{std::move(set)};
-    entt::storage<std::uint64_t, int> other;
+    (void)entt::storage<entt::entity, int>{std::move(set)};
+    entt::storage<entt::entity, int> other;
     other = std::move(set);
     other = std::move(set);
 }
 }
 
 
 TEST(Storage, EmptyType) {
 TEST(Storage, EmptyType) {
-    entt::storage<std::uint64_t, empty_type> set;
+    entt::storage<entt::entity, empty_type> set;
 
 
-    set.construct(42);
-    set.construct(99);
+    set.construct(entt::entity{42});
+    set.construct(entt::entity{99});
 
 
-    ASSERT_TRUE(set.has(42));
-    ASSERT_TRUE(set.has(99));
+    ASSERT_TRUE(set.has(entt::entity{42}));
+    ASSERT_TRUE(set.has(entt::entity{99}));
 
 
-    auto &&component = set.get(42);
+    auto &&component = set.get(entt::entity{42});
 
 
     ASSERT_TRUE((std::is_same_v<decltype(component), empty_type &&>));
     ASSERT_TRUE((std::is_same_v<decltype(component), empty_type &&>));
 }
 }
 
 
 TEST(Storage, BatchAdd) {
 TEST(Storage, BatchAdd) {
-    entt::storage<std::uint64_t, int> set;
-    entt::storage<std::uint64_t, int>::entity_type entities[2];
+    entt::storage<entt::entity, int> set;
+    entt::storage<entt::entity, int>::entity_type entities[2];
 
 
-    entities[0] = 3;
-    entities[1] = 42;
+    entities[0] = entt::entity{3};
+    entities[1] = entt::entity{42};
 
 
     set.reserve(4);
     set.reserve(4);
-    set.construct(12, 21);
+    set.construct(entt::entity{12}, 21);
     auto *component = set.batch(std::begin(entities), std::end(entities));
     auto *component = set.batch(std::begin(entities), std::end(entities));
-    set.construct(24, 42);
+    set.construct(entt::entity{24}, 42);
 
 
     ASSERT_TRUE(set.has(entities[0]));
     ASSERT_TRUE(set.has(entities[0]));
     ASSERT_TRUE(set.has(entities[1]));
     ASSERT_TRUE(set.has(entities[1]));
-    ASSERT_FALSE(set.has(0));
-    ASSERT_FALSE(set.has(9));
-    ASSERT_TRUE(set.has(12));
-    ASSERT_TRUE(set.has(24));
+    ASSERT_FALSE(set.has(entt::entity{0}));
+    ASSERT_FALSE(set.has(entt::entity{9}));
+    ASSERT_TRUE(set.has(entt::entity{12}));
+    ASSERT_TRUE(set.has(entt::entity{24}));
 
 
     ASSERT_FALSE(set.empty());
     ASSERT_FALSE(set.empty());
     ASSERT_EQ(set.size(), 4u);
     ASSERT_EQ(set.size(), 4u);
-    ASSERT_EQ(set.get(12), 21);
+    ASSERT_EQ(set.get(entt::entity{12}), 21);
     ASSERT_EQ(set.get(entities[0]), 0);
     ASSERT_EQ(set.get(entities[0]), 0);
     ASSERT_EQ(set.get(entities[1]), 0);
     ASSERT_EQ(set.get(entities[1]), 0);
-    ASSERT_EQ(set.get(24), 42);
+    ASSERT_EQ(set.get(entt::entity{24}), 42);
 
 
     component[0] = 1;
     component[0] = 1;
     component[1] = 2;
     component[1] = 2;
@@ -127,23 +128,23 @@ TEST(Storage, BatchAdd) {
 }
 }
 
 
 TEST(Storage, BatchAddEmptyType) {
 TEST(Storage, BatchAddEmptyType) {
-    entt::storage<std::uint64_t, empty_type> set;
-    entt::storage<std::uint64_t, empty_type>::entity_type entities[2];
+    entt::storage<entt::entity, empty_type> set;
+    entt::storage<entt::entity, empty_type>::entity_type entities[2];
 
 
-    entities[0] = 3;
-    entities[1] = 42;
+    entities[0] = entt::entity{3};
+    entities[1] = entt::entity{42};
 
 
     set.reserve(4);
     set.reserve(4);
-    set.construct(12);
+    set.construct(entt::entity{12});
     set.batch(std::begin(entities), std::end(entities));
     set.batch(std::begin(entities), std::end(entities));
-    set.construct(24);
+    set.construct(entt::entity{24});
 
 
     ASSERT_TRUE(set.has(entities[0]));
     ASSERT_TRUE(set.has(entities[0]));
     ASSERT_TRUE(set.has(entities[1]));
     ASSERT_TRUE(set.has(entities[1]));
-    ASSERT_FALSE(set.has(0));
-    ASSERT_FALSE(set.has(9));
-    ASSERT_TRUE(set.has(12));
-    ASSERT_TRUE(set.has(24));
+    ASSERT_FALSE(set.has(entt::entity{0}));
+    ASSERT_FALSE(set.has(entt::entity{9}));
+    ASSERT_TRUE(set.has(entt::entity{12}));
+    ASSERT_TRUE(set.has(entt::entity{24}));
 
 
     ASSERT_FALSE(set.empty());
     ASSERT_FALSE(set.empty());
     ASSERT_EQ(set.size(), 4u);
     ASSERT_EQ(set.size(), 4u);
@@ -156,21 +157,21 @@ TEST(Storage, BatchAddEmptyType) {
 TEST(Storage, AggregatesMustWork) {
 TEST(Storage, AggregatesMustWork) {
     struct aggregate_type { int value; };
     struct aggregate_type { int value; };
     // the goal of this test is to enforce the requirements for aggregate types
     // the goal of this test is to enforce the requirements for aggregate types
-    entt::storage<std::uint64_t, aggregate_type>{}.construct(0, 42);
+    entt::storage<entt::entity, aggregate_type>{}.construct(entt::entity{0}, 42);
 }
 }
 
 
 TEST(Storage, TypesFromStandardTemplateLibraryMustWork) {
 TEST(Storage, TypesFromStandardTemplateLibraryMustWork) {
     // see #37 - this test shouldn't crash, that's all
     // see #37 - this test shouldn't crash, that's all
-    entt::storage<std::uint64_t, std::unordered_set<int>> set;
-    set.construct(0).insert(42);
-    set.destroy(0);
+    entt::storage<entt::entity, std::unordered_set<int>> set;
+    set.construct(entt::entity{0}).insert(42);
+    set.destroy(entt::entity{0});
 }
 }
 
 
 TEST(Storage, Iterator) {
 TEST(Storage, Iterator) {
-    using iterator_type = typename entt::storage<std::uint64_t, boxed_int>::iterator_type;
+    using iterator_type = typename entt::storage<entt::entity, boxed_int>::iterator_type;
 
 
-    entt::storage<std::uint64_t, boxed_int> set;
-    set.construct(3, 42);
+    entt::storage<entt::entity, boxed_int> set;
+    set.construct(entt::entity{3}, 42);
 
 
     iterator_type end{set.begin()};
     iterator_type end{set.begin()};
     iterator_type begin{};
     iterator_type begin{};
@@ -209,10 +210,10 @@ TEST(Storage, Iterator) {
 }
 }
 
 
 TEST(Storage, ConstIterator) {
 TEST(Storage, ConstIterator) {
-    using iterator_type = typename entt::storage<std::uint64_t, boxed_int>::const_iterator_type;
+    using iterator_type = typename entt::storage<entt::entity, boxed_int>::const_iterator_type;
 
 
-    entt::storage<std::uint64_t, boxed_int> set;
-    set.construct(3, 42);
+    entt::storage<entt::entity, boxed_int> set;
+    set.construct(entt::entity{3}, 42);
 
 
     iterator_type cend{set.cbegin()};
     iterator_type cend{set.cbegin()};
     iterator_type cbegin{};
     iterator_type cbegin{};
@@ -251,9 +252,9 @@ TEST(Storage, ConstIterator) {
 }
 }
 
 
 TEST(Storage, IteratorEmptyType) {
 TEST(Storage, IteratorEmptyType) {
-    using iterator_type = typename entt::storage<std::uint64_t, empty_type>::iterator_type;
-    entt::storage<std::uint64_t, empty_type> set;
-    set.construct(3);
+    using iterator_type = typename entt::storage<entt::entity, empty_type>::iterator_type;
+    entt::storage<entt::entity, empty_type> set;
+    set.construct(entt::entity{3});
 
 
     iterator_type end{set.begin()};
     iterator_type end{set.begin()};
     iterator_type begin{};
     iterator_type begin{};
@@ -290,22 +291,22 @@ TEST(Storage, IteratorEmptyType) {
     ASSERT_GT(end, begin);
     ASSERT_GT(end, begin);
     ASSERT_GE(end, set.end());
     ASSERT_GE(end, set.end());
 
 
-    set.construct(33);
+    set.construct(entt::entity{33});
     auto &&component = *begin;
     auto &&component = *begin;
 
 
     ASSERT_TRUE((std::is_same_v<decltype(component), empty_type &&>));
     ASSERT_TRUE((std::is_same_v<decltype(component), empty_type &&>));
 }
 }
 
 
 TEST(Storage, Raw) {
 TEST(Storage, Raw) {
-    entt::storage<std::uint64_t, int> set;
+    entt::storage<entt::entity, int> set;
 
 
-    set.construct(3, 3);
-    set.construct(12, 6);
-    set.construct(42, 9);
+    set.construct(entt::entity{3}, 3);
+    set.construct(entt::entity{12}, 6);
+    set.construct(entt::entity{42}, 9);
 
 
-    ASSERT_EQ(set.get(3), 3);
-    ASSERT_EQ(std::as_const(set).get(12), 6);
-    ASSERT_EQ(set.get(42), 9);
+    ASSERT_EQ(set.get(entt::entity{3}), 3);
+    ASSERT_EQ(std::as_const(set).get(entt::entity{12}), 6);
+    ASSERT_EQ(set.get(entt::entity{42}), 9);
 
 
     ASSERT_EQ(*(set.raw() + 0u), 3);
     ASSERT_EQ(*(set.raw() + 0u), 3);
     ASSERT_EQ(*(std::as_const(set).raw() + 1u), 6);
     ASSERT_EQ(*(std::as_const(set).raw() + 1u), 6);
@@ -313,19 +314,19 @@ TEST(Storage, Raw) {
 }
 }
 
 
 TEST(Storage, SortOrdered) {
 TEST(Storage, SortOrdered) {
-    entt::storage<std::uint64_t, boxed_int> set;
+    entt::storage<entt::entity, boxed_int> set;
 
 
-    set.construct(12, boxed_int{12});
-    set.construct(42, boxed_int{9});
-    set.construct(7, boxed_int{6});
-    set.construct(3, boxed_int{3});
-    set.construct(9, boxed_int{1});
+    set.construct(entt::entity{12}, boxed_int{12});
+    set.construct(entt::entity{42}, boxed_int{9});
+    set.construct(entt::entity{7}, boxed_int{6});
+    set.construct(entt::entity{3}, boxed_int{3});
+    set.construct(entt::entity{9}, boxed_int{1});
 
 
-    ASSERT_EQ(set.get(12).value, 12);
-    ASSERT_EQ(set.get(42).value, 9);
-    ASSERT_EQ(set.get(7).value, 6);
-    ASSERT_EQ(set.get(3).value, 3);
-    ASSERT_EQ(set.get(9).value, 1);
+    ASSERT_EQ(set.get(entt::entity{12}).value, 12);
+    ASSERT_EQ(set.get(entt::entity{42}).value, 9);
+    ASSERT_EQ(set.get(entt::entity{7}).value, 6);
+    ASSERT_EQ(set.get(entt::entity{3}).value, 3);
+    ASSERT_EQ(set.get(entt::entity{9}).value, 1);
 
 
     set.sort([](auto lhs, auto rhs) {
     set.sort([](auto lhs, auto rhs) {
         return lhs.value < rhs.value;
         return lhs.value < rhs.value;
@@ -349,21 +350,21 @@ TEST(Storage, SortOrdered) {
 }
 }
 
 
 TEST(Storage, SortReverse) {
 TEST(Storage, SortReverse) {
-    entt::storage<std::uint64_t, boxed_int> set;
+    entt::storage<entt::entity, boxed_int> set;
 
 
-    set.construct(12, boxed_int{1});
-    set.construct(42, boxed_int{3});
-    set.construct(7, boxed_int{6});
-    set.construct(3, boxed_int{9});
-    set.construct(9, boxed_int{12});
+    set.construct(entt::entity{12}, boxed_int{1});
+    set.construct(entt::entity{42}, boxed_int{3});
+    set.construct(entt::entity{7}, boxed_int{6});
+    set.construct(entt::entity{3}, boxed_int{9});
+    set.construct(entt::entity{9}, boxed_int{12});
 
 
-    ASSERT_EQ(set.get(12).value, 1);
-    ASSERT_EQ(set.get(42).value, 3);
-    ASSERT_EQ(set.get(7).value, 6);
-    ASSERT_EQ(set.get(3).value, 9);
-    ASSERT_EQ(set.get(9).value, 12);
+    ASSERT_EQ(set.get(entt::entity{12}).value, 1);
+    ASSERT_EQ(set.get(entt::entity{42}).value, 3);
+    ASSERT_EQ(set.get(entt::entity{7}).value, 6);
+    ASSERT_EQ(set.get(entt::entity{3}).value, 9);
+    ASSERT_EQ(set.get(entt::entity{9}).value, 12);
 
 
-    set.sort([&set](std::uint64_t lhs, std::uint64_t rhs) {
+    set.sort([&set](entt::entity lhs, entt::entity rhs) {
         return set.get(lhs).value < set.get(rhs).value;
         return set.get(lhs).value < set.get(rhs).value;
     });
     });
 
 
@@ -385,19 +386,19 @@ TEST(Storage, SortReverse) {
 }
 }
 
 
 TEST(Storage, SortUnordered) {
 TEST(Storage, SortUnordered) {
-    entt::storage<std::uint64_t, boxed_int> set;
+    entt::storage<entt::entity, boxed_int> set;
 
 
-    set.construct(12, boxed_int{6});
-    set.construct(42, boxed_int{3});
-    set.construct(7, boxed_int{1});
-    set.construct(3, boxed_int{9});
-    set.construct(9, boxed_int{12});
+    set.construct(entt::entity{12}, boxed_int{6});
+    set.construct(entt::entity{42}, boxed_int{3});
+    set.construct(entt::entity{7}, boxed_int{1});
+    set.construct(entt::entity{3}, boxed_int{9});
+    set.construct(entt::entity{9}, boxed_int{12});
 
 
-    ASSERT_EQ(set.get(12).value, 6);
-    ASSERT_EQ(set.get(42).value, 3);
-    ASSERT_EQ(set.get(7).value, 1);
-    ASSERT_EQ(set.get(3).value, 9);
-    ASSERT_EQ(set.get(9).value, 12);
+    ASSERT_EQ(set.get(entt::entity{12}).value, 6);
+    ASSERT_EQ(set.get(entt::entity{42}).value, 3);
+    ASSERT_EQ(set.get(entt::entity{7}).value, 1);
+    ASSERT_EQ(set.get(entt::entity{3}).value, 9);
+    ASSERT_EQ(set.get(entt::entity{9}).value, 12);
 
 
     set.sort([](auto lhs, auto rhs) {
     set.sort([](auto lhs, auto rhs) {
         return lhs.value < rhs.value;
         return lhs.value < rhs.value;
@@ -421,16 +422,16 @@ TEST(Storage, SortUnordered) {
 }
 }
 
 
 TEST(Storage, RespectDisjoint) {
 TEST(Storage, RespectDisjoint) {
-    entt::storage<std::uint64_t, int> lhs;
-    entt::storage<std::uint64_t, int> rhs;
+    entt::storage<entt::entity, int> lhs;
+    entt::storage<entt::entity, int> rhs;
 
 
-    lhs.construct(3, 3);
-    lhs.construct(12, 6);
-    lhs.construct(42, 9);
+    lhs.construct(entt::entity{3}, 3);
+    lhs.construct(entt::entity{12}, 6);
+    lhs.construct(entt::entity{42}, 9);
 
 
-    ASSERT_EQ(std::as_const(lhs).get(3), 3);
-    ASSERT_EQ(std::as_const(lhs).get(12), 6);
-    ASSERT_EQ(std::as_const(lhs).get(42), 9);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{3}), 3);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{12}), 6);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{42}), 9);
 
 
     lhs.respect(rhs);
     lhs.respect(rhs);
 
 
@@ -448,18 +449,18 @@ TEST(Storage, RespectDisjoint) {
 }
 }
 
 
 TEST(Storage, RespectOverlap) {
 TEST(Storage, RespectOverlap) {
-    entt::storage<std::uint64_t, int> lhs;
-    entt::storage<std::uint64_t, int> rhs;
+    entt::storage<entt::entity, int> lhs;
+    entt::storage<entt::entity, int> rhs;
 
 
-    lhs.construct(3, 3);
-    lhs.construct(12, 6);
-    lhs.construct(42, 9);
-    rhs.construct(12, 6);
+    lhs.construct(entt::entity{3}, 3);
+    lhs.construct(entt::entity{12}, 6);
+    lhs.construct(entt::entity{42}, 9);
+    rhs.construct(entt::entity{12}, 6);
 
 
-    ASSERT_EQ(std::as_const(lhs).get(3), 3);
-    ASSERT_EQ(std::as_const(lhs).get(12), 6);
-    ASSERT_EQ(std::as_const(lhs).get(42), 9);
-    ASSERT_EQ(rhs.get(12), 6);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{3}), 3);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{12}), 6);
+    ASSERT_EQ(std::as_const(lhs).get(entt::entity{42}), 9);
+    ASSERT_EQ(rhs.get(entt::entity{12}), 6);
 
 
     lhs.respect(rhs);
     lhs.respect(rhs);
 
 
@@ -477,174 +478,174 @@ TEST(Storage, RespectOverlap) {
 }
 }
 
 
 TEST(Storage, RespectOrdered) {
 TEST(Storage, RespectOrdered) {
-    entt::storage<std::uint64_t, int> lhs;
-    entt::storage<std::uint64_t, int> rhs;
-
-    lhs.construct(1, 0);
-    lhs.construct(2, 0);
-    lhs.construct(3, 0);
-    lhs.construct(4, 0);
-    lhs.construct(5, 0);
-
-    ASSERT_EQ(lhs.get(1), 0);
-    ASSERT_EQ(lhs.get(2), 0);
-    ASSERT_EQ(lhs.get(3), 0);
-    ASSERT_EQ(lhs.get(4), 0);
-    ASSERT_EQ(lhs.get(5), 0);
-
-    rhs.construct(6, 0);
-    rhs.construct(1, 0);
-    rhs.construct(2, 0);
-    rhs.construct(3, 0);
-    rhs.construct(4, 0);
-    rhs.construct(5, 0);
-
-    ASSERT_EQ(rhs.get(6), 0);
-    ASSERT_EQ(rhs.get(1), 0);
-    ASSERT_EQ(rhs.get(2), 0);
-    ASSERT_EQ(rhs.get(3), 0);
-    ASSERT_EQ(rhs.get(4), 0);
-    ASSERT_EQ(rhs.get(5), 0);
+    entt::storage<entt::entity, int> lhs;
+    entt::storage<entt::entity, int> rhs;
+
+    lhs.construct(entt::entity{1}, 0);
+    lhs.construct(entt::entity{2}, 0);
+    lhs.construct(entt::entity{3}, 0);
+    lhs.construct(entt::entity{4}, 0);
+    lhs.construct(entt::entity{5}, 0);
+
+    ASSERT_EQ(lhs.get(entt::entity{1}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{2}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{3}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{4}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{5}), 0);
+
+    rhs.construct(entt::entity{6}, 0);
+    rhs.construct(entt::entity{1}, 0);
+    rhs.construct(entt::entity{2}, 0);
+    rhs.construct(entt::entity{3}, 0);
+    rhs.construct(entt::entity{4}, 0);
+    rhs.construct(entt::entity{5}, 0);
+
+    ASSERT_EQ(rhs.get(entt::entity{6}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{1}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{2}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{3}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{4}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{5}), 0);
 
 
     rhs.respect(lhs);
     rhs.respect(lhs);
 
 
-    ASSERT_EQ(*(lhs.data() + 0u), 1u);
-    ASSERT_EQ(*(lhs.data() + 1u), 2u);
-    ASSERT_EQ(*(lhs.data() + 2u), 3u);
-    ASSERT_EQ(*(lhs.data() + 3u), 4u);
-    ASSERT_EQ(*(lhs.data() + 4u), 5u);
-
-    ASSERT_EQ(*(rhs.data() + 0u), 6u);
-    ASSERT_EQ(*(rhs.data() + 1u), 1u);
-    ASSERT_EQ(*(rhs.data() + 2u), 2u);
-    ASSERT_EQ(*(rhs.data() + 3u), 3u);
-    ASSERT_EQ(*(rhs.data() + 4u), 4u);
-    ASSERT_EQ(*(rhs.data() + 5u), 5u);
+    ASSERT_EQ(*(lhs.data() + 0u), entt::entity{1});
+    ASSERT_EQ(*(lhs.data() + 1u), entt::entity{2});
+    ASSERT_EQ(*(lhs.data() + 2u), entt::entity{3});
+    ASSERT_EQ(*(lhs.data() + 3u), entt::entity{4});
+    ASSERT_EQ(*(lhs.data() + 4u), entt::entity{5});
+
+    ASSERT_EQ(*(rhs.data() + 0u), entt::entity{6});
+    ASSERT_EQ(*(rhs.data() + 1u), entt::entity{1});
+    ASSERT_EQ(*(rhs.data() + 2u), entt::entity{2});
+    ASSERT_EQ(*(rhs.data() + 3u), entt::entity{3});
+    ASSERT_EQ(*(rhs.data() + 4u), entt::entity{4});
+    ASSERT_EQ(*(rhs.data() + 5u), entt::entity{5});
 }
 }
 
 
 TEST(Storage, RespectReverse) {
 TEST(Storage, RespectReverse) {
-    entt::storage<std::uint64_t, int> lhs;
-    entt::storage<std::uint64_t, int> rhs;
-
-    lhs.construct(1, 0);
-    lhs.construct(2, 0);
-    lhs.construct(3, 0);
-    lhs.construct(4, 0);
-    lhs.construct(5, 0);
-
-    ASSERT_EQ(lhs.get(1), 0);
-    ASSERT_EQ(lhs.get(2), 0);
-    ASSERT_EQ(lhs.get(3), 0);
-    ASSERT_EQ(lhs.get(4), 0);
-    ASSERT_EQ(lhs.get(5), 0);
-
-    rhs.construct(5, 0);
-    rhs.construct(4, 0);
-    rhs.construct(3, 0);
-    rhs.construct(2, 0);
-    rhs.construct(1, 0);
-    rhs.construct(6, 0);
-
-    ASSERT_EQ(rhs.get(5), 0);
-    ASSERT_EQ(rhs.get(4), 0);
-    ASSERT_EQ(rhs.get(3), 0);
-    ASSERT_EQ(rhs.get(2), 0);
-    ASSERT_EQ(rhs.get(1), 0);
-    ASSERT_EQ(rhs.get(6), 0);
+    entt::storage<entt::entity, int> lhs;
+    entt::storage<entt::entity, int> rhs;
+
+    lhs.construct(entt::entity{1}, 0);
+    lhs.construct(entt::entity{2}, 0);
+    lhs.construct(entt::entity{3}, 0);
+    lhs.construct(entt::entity{4}, 0);
+    lhs.construct(entt::entity{5}, 0);
+
+    ASSERT_EQ(lhs.get(entt::entity{1}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{2}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{3}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{4}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{5}), 0);
+
+    rhs.construct(entt::entity{5}, 0);
+    rhs.construct(entt::entity{4}, 0);
+    rhs.construct(entt::entity{3}, 0);
+    rhs.construct(entt::entity{2}, 0);
+    rhs.construct(entt::entity{1}, 0);
+    rhs.construct(entt::entity{6}, 0);
+
+    ASSERT_EQ(rhs.get(entt::entity{5}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{4}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{3}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{2}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{1}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{6}), 0);
 
 
     rhs.respect(lhs);
     rhs.respect(lhs);
 
 
-    ASSERT_EQ(*(lhs.data() + 0u), 1u);
-    ASSERT_EQ(*(lhs.data() + 1u), 2u);
-    ASSERT_EQ(*(lhs.data() + 2u), 3u);
-    ASSERT_EQ(*(lhs.data() + 3u), 4u);
-    ASSERT_EQ(*(lhs.data() + 4u), 5u);
-
-    ASSERT_EQ(*(rhs.data() + 0u), 6u);
-    ASSERT_EQ(*(rhs.data() + 1u), 1u);
-    ASSERT_EQ(*(rhs.data() + 2u), 2u);
-    ASSERT_EQ(*(rhs.data() + 3u), 3u);
-    ASSERT_EQ(*(rhs.data() + 4u), 4u);
-    ASSERT_EQ(*(rhs.data() + 5u), 5u);
+    ASSERT_EQ(*(lhs.data() + 0u), entt::entity{1});
+    ASSERT_EQ(*(lhs.data() + 1u), entt::entity{2});
+    ASSERT_EQ(*(lhs.data() + 2u), entt::entity{3});
+    ASSERT_EQ(*(lhs.data() + 3u), entt::entity{4});
+    ASSERT_EQ(*(lhs.data() + 4u), entt::entity{5});
+
+    ASSERT_EQ(*(rhs.data() + 0u), entt::entity{6});
+    ASSERT_EQ(*(rhs.data() + 1u), entt::entity{1});
+    ASSERT_EQ(*(rhs.data() + 2u), entt::entity{2});
+    ASSERT_EQ(*(rhs.data() + 3u), entt::entity{3});
+    ASSERT_EQ(*(rhs.data() + 4u), entt::entity{4});
+    ASSERT_EQ(*(rhs.data() + 5u), entt::entity{5});
 }
 }
 
 
 TEST(Storage, RespectUnordered) {
 TEST(Storage, RespectUnordered) {
-    entt::storage<std::uint64_t, int> lhs;
-    entt::storage<std::uint64_t, int> rhs;
-
-    lhs.construct(1, 0);
-    lhs.construct(2, 0);
-    lhs.construct(3, 0);
-    lhs.construct(4, 0);
-    lhs.construct(5, 0);
-
-    ASSERT_EQ(lhs.get(1), 0);
-    ASSERT_EQ(lhs.get(2), 0);
-    ASSERT_EQ(lhs.get(3), 0);
-    ASSERT_EQ(lhs.get(4), 0);
-    ASSERT_EQ(lhs.get(5), 0);
-
-    rhs.construct(3, 0);
-    rhs.construct(2, 0);
-    rhs.construct(6, 0);
-    rhs.construct(1, 0);
-    rhs.construct(4, 0);
-    rhs.construct(5, 0);
-
-    ASSERT_EQ(rhs.get(3), 0);
-    ASSERT_EQ(rhs.get(2), 0);
-    ASSERT_EQ(rhs.get(6), 0);
-    ASSERT_EQ(rhs.get(1), 0);
-    ASSERT_EQ(rhs.get(4), 0);
-    ASSERT_EQ(rhs.get(5), 0);
+    entt::storage<entt::entity, int> lhs;
+    entt::storage<entt::entity, int> rhs;
+
+    lhs.construct(entt::entity{1}, 0);
+    lhs.construct(entt::entity{2}, 0);
+    lhs.construct(entt::entity{3}, 0);
+    lhs.construct(entt::entity{4}, 0);
+    lhs.construct(entt::entity{5}, 0);
+
+    ASSERT_EQ(lhs.get(entt::entity{1}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{2}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{3}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{4}), 0);
+    ASSERT_EQ(lhs.get(entt::entity{5}), 0);
+
+    rhs.construct(entt::entity{3}, 0);
+    rhs.construct(entt::entity{2}, 0);
+    rhs.construct(entt::entity{6}, 0);
+    rhs.construct(entt::entity{1}, 0);
+    rhs.construct(entt::entity{4}, 0);
+    rhs.construct(entt::entity{5}, 0);
+
+    ASSERT_EQ(rhs.get(entt::entity{3}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{2}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{6}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{1}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{4}), 0);
+    ASSERT_EQ(rhs.get(entt::entity{5}), 0);
 
 
     rhs.respect(lhs);
     rhs.respect(lhs);
 
 
-    ASSERT_EQ(*(lhs.data() + 0u), 1u);
-    ASSERT_EQ(*(lhs.data() + 1u), 2u);
-    ASSERT_EQ(*(lhs.data() + 2u), 3u);
-    ASSERT_EQ(*(lhs.data() + 3u), 4u);
-    ASSERT_EQ(*(lhs.data() + 4u), 5u);
-
-    ASSERT_EQ(*(rhs.data() + 0u), 6u);
-    ASSERT_EQ(*(rhs.data() + 1u), 1u);
-    ASSERT_EQ(*(rhs.data() + 2u), 2u);
-    ASSERT_EQ(*(rhs.data() + 3u), 3u);
-    ASSERT_EQ(*(rhs.data() + 4u), 4u);
-    ASSERT_EQ(*(rhs.data() + 5u), 5u);
+    ASSERT_EQ(*(lhs.data() + 0u), entt::entity{1});
+    ASSERT_EQ(*(lhs.data() + 1u), entt::entity{2});
+    ASSERT_EQ(*(lhs.data() + 2u), entt::entity{3});
+    ASSERT_EQ(*(lhs.data() + 3u), entt::entity{4});
+    ASSERT_EQ(*(lhs.data() + 4u), entt::entity{5});
+
+    ASSERT_EQ(*(rhs.data() + 0u), entt::entity{6});
+    ASSERT_EQ(*(rhs.data() + 1u), entt::entity{1});
+    ASSERT_EQ(*(rhs.data() + 2u), entt::entity{2});
+    ASSERT_EQ(*(rhs.data() + 3u), entt::entity{3});
+    ASSERT_EQ(*(rhs.data() + 4u), entt::entity{4});
+    ASSERT_EQ(*(rhs.data() + 5u), entt::entity{5});
 }
 }
 
 
 TEST(Storage, RespectOverlapEmptyType) {
 TEST(Storage, RespectOverlapEmptyType) {
-    entt::storage<std::uint64_t, empty_type> lhs;
-    entt::storage<std::uint64_t, empty_type> rhs;
+    entt::storage<entt::entity, empty_type> lhs;
+    entt::storage<entt::entity, empty_type> rhs;
 
 
-    lhs.construct(3);
-    lhs.construct(12);
-    lhs.construct(42);
+    lhs.construct(entt::entity{3});
+    lhs.construct(entt::entity{12});
+    lhs.construct(entt::entity{42});
 
 
-    rhs.construct(12);
+    rhs.construct(entt::entity{12});
 
 
-    ASSERT_EQ(lhs.sparse_set<std::uint64_t>::get(3), 0u);
-    ASSERT_EQ(lhs.sparse_set<std::uint64_t>::get(12), 1u);
-    ASSERT_EQ(lhs.sparse_set<std::uint64_t>::get(42), 2u);
+    ASSERT_EQ(lhs.sparse_set<entt::entity>::get(entt::entity{3}), 0u);
+    ASSERT_EQ(lhs.sparse_set<entt::entity>::get(entt::entity{12}), 1u);
+    ASSERT_EQ(lhs.sparse_set<entt::entity>::get(entt::entity{42}), 2u);
 
 
     lhs.respect(rhs);
     lhs.respect(rhs);
 
 
-    ASSERT_EQ(std::as_const(lhs).sparse_set<std::uint64_t>::get(3), 0u);
-    ASSERT_EQ(std::as_const(lhs).sparse_set<std::uint64_t>::get(12), 2u);
-    ASSERT_EQ(std::as_const(lhs).sparse_set<std::uint64_t>::get(42), 1u);
+    ASSERT_EQ(std::as_const(lhs).sparse_set<entt::entity>::get(entt::entity{3}), 0u);
+    ASSERT_EQ(std::as_const(lhs).sparse_set<entt::entity>::get(entt::entity{12}), 2u);
+    ASSERT_EQ(std::as_const(lhs).sparse_set<entt::entity>::get(entt::entity{42}), 1u);
 }
 }
 
 
 TEST(Storage, CanModifyDuringIteration) {
 TEST(Storage, CanModifyDuringIteration) {
-    entt::storage<std::uint64_t, int> set;
-    set.construct(0, 42);
+    entt::storage<entt::entity, int> set;
+    set.construct(entt::entity{0}, 42);
 
 
-    ASSERT_EQ(set.capacity(), (entt::storage<std::uint64_t, int>::size_type{1}));
+    ASSERT_EQ(set.capacity(), (entt::storage<entt::entity, int>::size_type{1}));
 
 
     const auto it = set.cbegin();
     const auto it = set.cbegin();
-    set.reserve(entt::storage<std::uint64_t, int>::size_type{2});
+    set.reserve(entt::storage<entt::entity, int>::size_type{2});
 
 
-    ASSERT_EQ(set.capacity(), (entt::storage<std::uint64_t, int>::size_type{2}));
+    ASSERT_EQ(set.capacity(), (entt::storage<entt::entity, int>::size_type{2}));
 
 
     // this should crash with asan enabled if we break the constraint
     // this should crash with asan enabled if we break the constraint
     const auto entity = *it;
     const auto entity = *it;
@@ -652,13 +653,13 @@ TEST(Storage, CanModifyDuringIteration) {
 }
 }
 
 
 TEST(Storage, ReferencesGuaranteed) {
 TEST(Storage, ReferencesGuaranteed) {
-    entt::storage<std::uint64_t, boxed_int> set;
+    entt::storage<entt::entity, boxed_int> set;
 
 
-    set.construct(0, 0);
-    set.construct(1, 1);
+    set.construct(entt::entity{0}, 0);
+    set.construct(entt::entity{1}, 1);
 
 
-    ASSERT_EQ(set.get(0).value, 0);
-    ASSERT_EQ(set.get(1).value, 1);
+    ASSERT_EQ(set.get(entt::entity{0}).value, 0);
+    ASSERT_EQ(set.get(entt::entity{1}).value, 1);
 
 
     for(auto &&type: set) {
     for(auto &&type: set) {
         if(type.value) {
         if(type.value) {
@@ -666,8 +667,8 @@ TEST(Storage, ReferencesGuaranteed) {
         }
         }
     }
     }
 
 
-    ASSERT_EQ(set.get(0).value, 0);
-    ASSERT_EQ(set.get(1).value, 42);
+    ASSERT_EQ(set.get(entt::entity{0}).value, 0);
+    ASSERT_EQ(set.get(entt::entity{1}).value, 42);
 
 
     auto begin = set.begin();
     auto begin = set.begin();
 
 
@@ -675,21 +676,21 @@ TEST(Storage, ReferencesGuaranteed) {
         (begin++)->value = 3;
         (begin++)->value = 3;
     }
     }
 
 
-    ASSERT_EQ(set.get(0).value, 3);
-    ASSERT_EQ(set.get(1).value, 3);
+    ASSERT_EQ(set.get(entt::entity{0}).value, 3);
+    ASSERT_EQ(set.get(entt::entity{1}).value, 3);
 }
 }
 
 
 TEST(Storage, MoveOnlyComponent) {
 TEST(Storage, MoveOnlyComponent) {
     // the purpose is to ensure that move only components are always accepted
     // the purpose is to ensure that move only components are always accepted
-    entt::storage<std::uint64_t, std::unique_ptr<int>> set;
+    entt::storage<entt::entity, std::unique_ptr<int>> set;
     (void)set;
     (void)set;
 }
 }
 
 
 TEST(Storage, ConstructorExceptionDoesNotAddToSet) {
 TEST(Storage, ConstructorExceptionDoesNotAddToSet) {
-    entt::storage<std::uint64_t, throwing_component> set;
+    entt::storage<entt::entity, throwing_component> set;
 
 
     try {
     try {
-        set.construct(0);
+        set.construct(entt::entity{0});
         FAIL() << "Expected constructor_exception to be thrown";
         FAIL() << "Expected constructor_exception to be thrown";
     } catch (const throwing_component::constructor_exception &) {
     } catch (const throwing_component::constructor_exception &) {
         ASSERT_TRUE(set.empty());
         ASSERT_TRUE(set.empty());

+ 5 - 5
test/entt/entity/view.cpp

@@ -136,9 +136,9 @@ TEST(SingleComponentView, ConstNonConstAndAllInBetween) {
     ASSERT_TRUE((std::is_same_v<typename decltype(view)::raw_type, int>));
     ASSERT_TRUE((std::is_same_v<typename decltype(view)::raw_type, int>));
     ASSERT_TRUE((std::is_same_v<typename decltype(cview)::raw_type, const int>));
     ASSERT_TRUE((std::is_same_v<typename decltype(cview)::raw_type, const int>));
 
 
-    ASSERT_TRUE((std::is_same_v<decltype(view.get(0)), int &>));
+    ASSERT_TRUE((std::is_same_v<decltype(view.get(entt::entity{0})), int &>));
     ASSERT_TRUE((std::is_same_v<decltype(view.raw()), int *>));
     ASSERT_TRUE((std::is_same_v<decltype(view.raw()), int *>));
-    ASSERT_TRUE((std::is_same_v<decltype(cview.get(0)), const int &>));
+    ASSERT_TRUE((std::is_same_v<decltype(cview.get(entt::entity{0})), const int &>));
     ASSERT_TRUE((std::is_same_v<decltype(cview.raw()), const int *>));
     ASSERT_TRUE((std::is_same_v<decltype(cview.raw()), const int *>));
 
 
     view.each([](auto, auto &&i) {
     view.each([](auto, auto &&i) {
@@ -416,9 +416,9 @@ TEST(MultipleComponentView, ConstNonConstAndAllInBetween) {
 
 
     ASSERT_EQ(view.size(), decltype(view.size()){1});
     ASSERT_EQ(view.size(), decltype(view.size()){1});
 
 
-    ASSERT_TRUE((std::is_same_v<decltype(view.get<int>(0)), int &>));
-    ASSERT_TRUE((std::is_same_v<decltype(view.get<const char>(0)), const char &>));
-    ASSERT_TRUE((std::is_same_v<decltype(view.get<int, const char>(0)), std::tuple<int &, const char &>>));
+    ASSERT_TRUE((std::is_same_v<decltype(view.get<int>(entt::entity{0})), int &>));
+    ASSERT_TRUE((std::is_same_v<decltype(view.get<const char>(entt::entity{0})), const char &>));
+    ASSERT_TRUE((std::is_same_v<decltype(view.get<int, const char>(entt::entity{0})), std::tuple<int &, const char &>>));
     ASSERT_TRUE((std::is_same_v<decltype(view.raw<const char>()), const char *>));
     ASSERT_TRUE((std::is_same_v<decltype(view.raw<const char>()), const char *>));
     ASSERT_TRUE((std::is_same_v<decltype(view.raw<int>()), int *>));
     ASSERT_TRUE((std::is_same_v<decltype(view.raw<int>()), int *>));
 
 

+ 4 - 3
test/lib/lib.cpp

@@ -1,7 +1,8 @@
+#include <gtest/gtest.h>
+#include <entt/entity/entity.hpp>
 #include <entt/entity/registry.hpp>
 #include <entt/entity/registry.hpp>
 #include <entt/signal/dispatcher.hpp>
 #include <entt/signal/dispatcher.hpp>
 #include <entt/signal/emitter.hpp>
 #include <entt/signal/emitter.hpp>
-#include <gtest/gtest.h>
 #include "types.h"
 #include "types.h"
 
 
 extern typename entt::registry::component_type a_module_int_type();
 extern typename entt::registry::component_type a_module_int_type();
@@ -58,8 +59,8 @@ TEST(Lib, Registry) {
     update_position(1, registry);
     update_position(1, registry);
 
 
     registry.view<position>().each([](auto entity, auto &position) {
     registry.view<position>().each([](auto entity, auto &position) {
-        ASSERT_EQ(position.x, entity + 2);
-        ASSERT_EQ(position.y, entity + 3);
+        ASSERT_EQ(position.x, entt::to_integer(entity) + 2);
+        ASSERT_EQ(position.y, entt::to_integer(entity) + 3);
     });
     });
 }
 }
 
 

+ 9 - 8
test/mod/mod.cpp

@@ -1,9 +1,9 @@
-#include <gtest/gtest.h>
 #include <type_traits>
 #include <type_traits>
 #include <cassert>
 #include <cassert>
 #include <map>
 #include <map>
 #include <string>
 #include <string>
 #include <duktape.h>
 #include <duktape.h>
+#include <gtest/gtest.h>
 #include <entt/entity/registry.hpp>
 #include <entt/entity/registry.hpp>
 
 
 template<typename Type>
 template<typename Type>
@@ -22,7 +22,7 @@ struct duktape_runtime {
 
 
 template<typename Comp>
 template<typename Comp>
 duk_ret_t set(duk_context *ctx, entt::registry &registry) {
 duk_ret_t set(duk_context *ctx, entt::registry &registry) {
-    const auto entity = duk_require_uint(ctx, 0);
+    const entt::entity entity{duk_require_uint(ctx, 0)};
 
 
     if constexpr(std::is_same_v<Comp, position>) {
     if constexpr(std::is_same_v<Comp, position>) {
         const auto x = duk_require_number(ctx, 2);
         const auto x = duk_require_number(ctx, 2);
@@ -49,7 +49,7 @@ duk_ret_t set(duk_context *ctx, entt::registry &registry) {
 
 
 template<typename Comp>
 template<typename Comp>
 duk_ret_t unset(duk_context *ctx, entt::registry &registry) {
 duk_ret_t unset(duk_context *ctx, entt::registry &registry) {
-    const auto entity = duk_require_uint(ctx, 0);
+    const entt::entity entity{duk_require_uint(ctx, 0)};
 
 
     if constexpr(std::is_same_v<Comp, duktape_runtime>) {
     if constexpr(std::is_same_v<Comp, duktape_runtime>) {
         const auto type = duk_require_uint(ctx, 1);
         const auto type = duk_require_uint(ctx, 1);
@@ -70,7 +70,7 @@ duk_ret_t unset(duk_context *ctx, entt::registry &registry) {
 
 
 template<typename Comp>
 template<typename Comp>
 duk_ret_t has(duk_context *ctx, entt::registry &registry) {
 duk_ret_t has(duk_context *ctx, entt::registry &registry) {
-    const auto entity = duk_require_uint(ctx, 0);
+    const entt::entity entity{duk_require_uint(ctx, 0)};
 
 
     if constexpr(std::is_same_v<Comp, duktape_runtime>) {
     if constexpr(std::is_same_v<Comp, duktape_runtime>) {
         duk_push_boolean(ctx, registry.has<duktape_runtime>(entity));
         duk_push_boolean(ctx, registry.has<duktape_runtime>(entity));
@@ -91,7 +91,7 @@ duk_ret_t has(duk_context *ctx, entt::registry &registry) {
 
 
 template<typename Comp>
 template<typename Comp>
 duk_ret_t get(duk_context *ctx, entt::registry &registry) {
 duk_ret_t get(duk_context *ctx, entt::registry &registry) {
-    [[maybe_unused]] const auto entity = duk_require_uint(ctx, 0);
+    [[maybe_unused]] const entt::entity entity{duk_require_uint(ctx, 0)};
 
 
     if constexpr(std::is_same_v<Comp, position>) {
     if constexpr(std::is_same_v<Comp, position>) {
         const auto &pos = registry.get<position>(entity);
         const auto &pos = registry.get<position>(entity);
@@ -186,7 +186,8 @@ public:
 
 
     static duk_ret_t create(duk_context *ctx) {
     static duk_ret_t create(duk_context *ctx) {
         auto &dreg = instance(ctx);
         auto &dreg = instance(ctx);
-        duk_push_uint(ctx, dreg.registry.create());
+        const auto entity = dreg.registry.create();
+        duk_push_uint(ctx, static_cast<std::underlying_type_t<entt::entity>>(entity));
         return 1;
         return 1;
     }
     }
 
 
@@ -234,7 +235,7 @@ public:
 
 
         for(const auto entity: view) {
         for(const auto entity: view) {
             if(runtime.empty()) {
             if(runtime.empty()) {
-                duk_push_uint(ctx, entity);
+                duk_push_uint(ctx, static_cast<std::underlying_type_t<entt::entity>>(entity));
                 duk_put_prop_index(ctx, -2, pos++);
                 duk_put_prop_index(ctx, -2, pos++);
             } else {
             } else {
                 const auto &others = dreg.registry.get<duktape_runtime>(entity).components;
                 const auto &others = dreg.registry.get<duktape_runtime>(entity).components;
@@ -243,7 +244,7 @@ public:
                 });
                 });
 
 
                 if(match) {
                 if(match) {
-                    duk_push_uint(ctx, entity);
+                    duk_push_uint(ctx, static_cast<std::underlying_type_t<entt::entity>>(entity));
                     duk_put_prop_index(ctx, -2, pos++);
                     duk_put_prop_index(ctx, -2, pos++);
                 }
                 }
             }
             }