Quellcode durchsuchen

type_info:
* make the API closer to that of std::type_info
* remove the ::seq member function
* rename :.hash to ::hash_code

Michele Caini vor 4 Jahren
Ursprung
Commit
6943822fed

+ 64 - 39
docs/md/core.md

@@ -17,7 +17,8 @@
   * [Small buffer optimization](#small-buffer-optimization)
   * [Alignment requirement](#alignment-requirement)
 * [Type support](#type-support)
-  * [Type info](#type-info)
+  * [Built-in RTTI support](#built-in-rtti-support)
+    * [Type info](#type-info)
     * [Almost unique identifiers](#almost-unique-identifiers)
   * [Type traits](#type-traits)
     * [Size of](#size-of)
@@ -369,30 +370,19 @@ that won't be able to interoperate with each other.
 It also offers additional features that are not yet available in the standard
 library or that will never be.
 
-## Type info
+## Built-in RTTI support
 
-The `type_info` class isn't a drop-in replacement for `std::type_info` but can
-provide similar information which are not implementation defined and don't
-require to enable RTTI.<br/>
-Therefore, they can sometimes be even more reliable than those obtained
-otherwise.
+Runtime type identification support (or RTTI) is one of the most frequently
+disabled features in the C++ world, especially in the gaming sector. Regardless
+of the reasons for this, it's often a shame not to be able to rely on opaque
+type information at runtime.<br/>
+The library tries to fill this gap by offering a built-in system that doesn't
+serve as a replacement but comes very close to being one and offers similar
+information to that provided by its counterpart.
 
-A type info object is an opaque class that is also copy and move constructible.
-This class is returned by the `type_id` function template:
-
-```cpp
-auto info = entt::type_id<a_type>();
-```
-
-These are the information made available by this object:
-
-* The unique, sequential identifier associated with a given type:
-
-  ```cpp
-  auto index = entt::type_id<a_type>().seq();
-  ```
+Basically, the whole system relies on a handful of classes. In particular:
 
-  This is also an alias for the following:
+* An unique, sequential identifier associated with a given type:
 
   ```cpp
   auto index = entt::type_seq<a_type>::value();
@@ -426,13 +416,7 @@ These are the information made available by this object:
   The tool is widely used within `EnTT`. Generating indices not sequentially
   would break an assumption and would likely lead to undesired behaviors.
 
-* The hash value associated with a given type:
-
-  ```cpp
-  auto hash = entt::type_id<a_type>().hash();
-  ```
-
-  This is also an alias for the following:
+* A hash value associated with a given type:
 
   ```cpp
   auto hash = entt::type_hash<a_type>::value();
@@ -440,9 +424,7 @@ These are the information made available by this object:
 
   In general, the `value` function exposed by `type_hash` is also `constexpr`
   but this isn't guaranteed for all compilers and platforms (although it's valid
-  with the most well-known and popular ones).<br/>
-  The `hash` function offered by the type info object isn't `constexpr` in any
-  case instead.
+  with the most well-known and popular ones).
 
   This function **can** use non-standard features of the language for its own
   purposes. This makes it possible to provide compile-time identifiers that
@@ -456,13 +438,7 @@ These are the information made available by this object:
   specialized in order to customize its behavior globally or on a per-type or
   per-traits basis.
 
-* The name associated with a given type:
-
-  ```cpp
-  auto name = entt::type_id<my_type>().name();
-  ```
-
-  This is also an alias for the following:
+* A name associated with a given type:
 
   ```cpp
   auto name = entt::type_name<a_type>::value();
@@ -495,6 +471,55 @@ These are the information made available by this object:
   specialized in order to customize its behavior globally or on a per-type or
   per-traits basis.
 
+These are then combined into utilities that aim to offer an API that is somewhat
+similar to that offered by the language.
+
+### Type info
+
+The `type_info` class isn't a drop-in replacement for `std::type_info` but can
+provide similar information which are not implementation defined and don't
+require to enable RTTI.<br/>
+Therefore, they can sometimes be even more reliable than those obtained
+otherwise.
+
+A type info object is an opaque class that is also copy and move constructible.
+This class is returned by the `type_id` function template:
+
+```cpp
+auto info = entt::type_id<a_type>();
+```
+
+These are the information made available by this object:
+
+* An unique, sequential identifier associated with a given type:
+
+  ```cpp
+  auto index = entt::type_id<a_type>().seq();
+  ```
+
+  This is also an alias for the following:
+
+  ```cpp
+  auto index = entt::type_seq<a_type>::value();
+  ```
+
+* A hash value associated with a given type:
+
+  ```cpp
+  auto hash = entt::type_id<a_type>().hash_code();
+  ```
+
+  This is also an alias for the following:
+
+  ```cpp
+  auto hash = entt::type_hash<a_type>::value();
+  ```
+
+Where all accessed features are available at compile-time, the `type_info` class
+is also fully `constexpr`. However, this cannot be guaranteed in advance and
+depends mainly on the compiler in use and any specializations of the classes
+described above.
+
 ### Almost unique identifiers
 
 Since the default non-standard, compile-time implementation of `type_hash` makes

+ 3 - 14
src/entt/core/type_info.hpp

@@ -151,8 +151,7 @@ struct type_name final {
 struct type_info final {
     /*! @brief Default constructor. */
     constexpr type_info() ENTT_NOEXCEPT
-        : index{},
-          identifier{},
+        : identifier{},
           alias{}
     {}
 
@@ -167,8 +166,7 @@ struct type_info final {
      */
     template<typename Type>
     constexpr type_info(std::in_place_type_t<Type>) ENTT_NOEXCEPT
-        : index{&type_seq<std::remove_reference_t<std::remove_const_t<Type>>>::value},
-          identifier{type_hash<std::remove_reference_t<std::remove_const_t<Type>>>::value()},
+        : identifier{type_hash<std::remove_reference_t<std::remove_const_t<Type>>>::value()},
           alias{type_name<std::remove_reference_t<std::remove_const_t<Type>>>::value()}
     {}
 
@@ -192,19 +190,11 @@ struct type_info final {
         return alias.data() != nullptr;
     }
 
-    /**
-     * @brief Type sequential identifier.
-     * @return Type sequential identifier.
-     */
-    [[nodiscard]] constexpr id_type seq() const ENTT_NOEXCEPT {
-        return index();
-    }
-
     /**
      * @brief Type hash.
      * @return Type hash.
      */
-    [[nodiscard]] constexpr id_type hash() const ENTT_NOEXCEPT {
+    [[nodiscard]] constexpr id_type hash_code() const ENTT_NOEXCEPT {
         return identifier;
     }
 
@@ -226,7 +216,6 @@ struct type_info final {
     }
 
 private:
-    id_type(* index)();
     id_type identifier;
     std::string_view alias;
 };

+ 8 - 6
src/entt/entity/registry.hpp

@@ -183,14 +183,16 @@ public:
      * empty and thus invalid element otherwise.
      */
     poly_storage & storage(const type_info info) {
-        ENTT_ASSERT(info.seq() < pools.size() && pools[info.seq()].poly, "Storage not available");
-        return pools[info.seq()].poly;
+        auto it = std::find_if(pools.begin(), pools.end(), [info](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash_code() == info.hash_code(); });
+        ENTT_ASSERT(it != pools.end(), "Storage not available");
+        return it->poly;
     }
 
     /*! @copydoc storage */
     const poly_storage & storage(const type_info info) const {
-        ENTT_ASSERT(info.seq() < pools.size() && pools[info.seq()].poly, "Storage not available");
-        return pools[info.seq()].poly;
+        auto it = std::find_if(pools.cbegin(), pools.cend(), [info](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash_code() == info.hash_code(); });
+        ENTT_ASSERT(it != pools.cend(), "Storage not available");
+        return it->poly;
     }
 
     /**
@@ -1165,12 +1167,12 @@ public:
         std::vector<const basic_common_type *> filter(std::distance(from, to));
 
         std::transform(first, last, component.begin(), [this](const auto ctype) {
-            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash() == ctype; });
+            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash_code() == ctype; });
             return it == pools.cend() ? nullptr : it->pool.get();
         });
 
         std::transform(from, to, filter.begin(), [this](const auto ctype) {
-            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash() == ctype; });
+            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.poly && pdata.poly->value_type().hash_code() == ctype; });
             return it == pools.cend() ? nullptr : it->pool.get();
         });
 

+ 4 - 5
test/entt/core/type_info.cpp

@@ -62,8 +62,7 @@ TEST(TypeInfo, Functionalities) {
     ASSERT_TRUE(info == info);
     ASSERT_FALSE(info != info);
 
-    ASSERT_EQ(info.seq(), entt::type_seq<int>::value());
-    ASSERT_EQ(info.hash(), entt::type_hash<int>::value());
+    ASSERT_EQ(info.hash_code(), entt::type_hash<int>::value());
     ASSERT_EQ(info.name(), entt::type_name<int>::value());
 
     ASSERT_TRUE(info);
@@ -73,15 +72,15 @@ TEST(TypeInfo, Functionalities) {
     empty = info;
 
     ASSERT_TRUE(empty);
-    ASSERT_EQ(empty.hash(), info.hash());
+    ASSERT_EQ(empty.hash_code(), info.hash_code());
 
     empty = {};
 
     ASSERT_FALSE(empty);
-    ASSERT_NE(empty.hash(), info.hash());
+    ASSERT_NE(empty.hash_code(), info.hash_code());
 
     empty = std::move(info);
 
     ASSERT_TRUE(empty);
-    ASSERT_EQ(empty.hash(), info.hash());
+    ASSERT_EQ(empty.hash_code(), info.hash_code());
 }

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

@@ -79,7 +79,7 @@ TEST(Registry, Context) {
     auto count = 0;
 
     registry.ctx([&count](auto info) {
-        ASSERT_EQ(info.hash(), entt::type_hash<char>::value());
+        ASSERT_EQ(info.hash_code(), entt::type_hash<char>::value());
         ++count;
     });
 
@@ -1881,9 +1881,9 @@ TEST(Registry, Visit) {
     bool hasType[3]{};
 
     registry.visit([&hasType](auto info) {
-        hasType[0] = hasType[0] || (info.hash() == entt::type_hash<int>::value());
-        hasType[1] = hasType[1] || (info.hash() == entt::type_hash<double>::value());
-        hasType[2] = hasType[2] || (info.hash() == entt::type_hash<char>::value());
+        hasType[0] = hasType[0] || (info.hash_code() == entt::type_hash<int>::value());
+        hasType[1] = hasType[1] || (info.hash_code() == entt::type_hash<double>::value());
+        hasType[2] = hasType[2] || (info.hash_code() == entt::type_hash<char>::value());
     });
 
     ASSERT_TRUE(hasType[0] && hasType[1] && hasType[2]);
@@ -1891,9 +1891,9 @@ TEST(Registry, Visit) {
     hasType[0] = hasType[1] = hasType[2] = false;
 
     registry.visit(entity, [&hasType](auto info) {
-        hasType[0] = hasType[0] || (info.hash() == entt::type_hash<int>::value());
-        hasType[1] = hasType[1] || (info.hash() == entt::type_hash<double>::value());
-        hasType[2] = hasType[2] || (info.hash() == entt::type_hash<char>::value());
+        hasType[0] = hasType[0] || (info.hash_code() == entt::type_hash<int>::value());
+        hasType[1] = hasType[1] || (info.hash_code() == entt::type_hash<double>::value());
+        hasType[2] = hasType[2] || (info.hash_code() == entt::type_hash<char>::value());
     });
 
     ASSERT_TRUE(hasType[0] && !hasType[1] && hasType[2]);
@@ -1901,9 +1901,9 @@ TEST(Registry, Visit) {
     hasType[0] = hasType[2] = false;
 
     registry.visit(other, [&hasType](auto info) {
-        hasType[0] = hasType[0] || (info.hash() == entt::type_hash<int>::value());
-        hasType[1] = hasType[1] || (info.hash() == entt::type_hash<double>::value());
-        hasType[2] = hasType[2] || (info.hash() == entt::type_hash<char>::value());
+        hasType[0] = hasType[0] || (info.hash_code() == entt::type_hash<int>::value());
+        hasType[1] = hasType[1] || (info.hash_code() == entt::type_hash<double>::value());
+        hasType[2] = hasType[2] || (info.hash_code() == entt::type_hash<char>::value());
     });
 
     ASSERT_TRUE(!hasType[0] && hasType[1] && !hasType[2]);