1
0
Эх сурвалжийг харах

handle: fixed an issue with the comparison operators + minor changes

Michele Caini 5 жил өмнө
parent
commit
3721a1f90b

+ 6 - 6
docs/md/entity.md

@@ -674,15 +674,15 @@ the requested method, passing on the arguments if necessary.
 
 ### Handle
 
-A handle is a thin wrapper around an entity and a registry. It provides the
-same functions that the registry offers for working with components, such as
+A handle is a thin wrapper around an entity and a registry. It provides the same
+functions that the registry offers for working with components, such as
 `emplace`, `get`, `patch`, `remove` and so on. The difference being that the
 entity is implicitly passed to the registry.<br/>
 It's default constructible as an invalid handle that contains a null registry
-and a null entity. When it contains a null registry calling functions that
-delegate execution to the registry will cause a crash, so it's recommended to
-check the validity of the handle with implicit cast to `bool` when in doubt.
-<br/>
+and a null entity. When it contains a null registry, calling functions that
+delegate execution to the registry will cause an undefined behavior, so it's
+recommended to check the validity of the handle with implicit cast to `bool`
+when in doubt.<br/>
 A handle is also non-owning, meaning that it can be freely copied and moved
 around without affecting its entity (in fact, handles happen to be trivially
 copyable). An implication of this is that mutability becomes part of the

+ 45 - 40
src/entt/entity/handle.hpp

@@ -19,19 +19,12 @@ template<typename Entity>
 struct basic_handle {
     /*! @brief Underlying entity identifier. */
     using entity_type = std::remove_const_t<Entity>;
-
     /*! @brief Type of registry accepted by the handle. */
-    using registry_type = std::conditional_t<
-        std::is_const_v<Entity>,
-        const basic_registry<entity_type>,
-        basic_registry<entity_type>
-    >;
+    using registry_type = std::conditional_t<std::is_const_v<Entity>, const basic_registry<entity_type>, basic_registry<entity_type>>;
 
-    /**
-     * @brief Constructs a default invalid handle.
-     */
+    /*! @brief Constructs an invalid handle. */
     basic_handle() ENTT_NOEXCEPT
-        : reg{nullptr}, entt{null}
+        : reg{}, entt{null}
     {}
 
     /**
@@ -45,26 +38,23 @@ struct basic_handle {
 
     /**
      * @brief Compares two handles.
-     * @return True if both handles refer to the same registry and the same entity, false otherwise.
+     * @tparam Type A valid entity type (see entt_traits for more details).
+     * @param other Handle with which to compare.
+     * @return True if both handles refer to the same registry and the same
+     * entity, false otherwise.
      */
-    bool operator==(const basic_handle<entity_type> &other) const ENTT_NOEXCEPT {
+    template<typename Type>
+    [[nodiscard]] bool operator==(const basic_handle<Type> &other) const ENTT_NOEXCEPT {
         return reg == other.registry() && entt == other.entity();
     }
 
-    /**
-     * @brief Compares two handles.
-     * @return False if both handles refer to the same registry and the same entity, true otherwise.
-     */
-    bool operator!=(const basic_handle<entity_type> &other) const ENTT_NOEXCEPT {
-        return !( *this == other);
-    }
-
     /**
      * @brief Constructs a const handle from a non-const one.
-     * @return A const handle referring to the same entity.
+     * @return A const handle referring to the same registry and the same
+     * entity.
      */
     [[nodiscard]] operator basic_handle<const entity_type>() const ENTT_NOEXCEPT {
-        return reg ? basic_handle<const entity_type>{ *reg, entt} : basic_handle<const entity_type>{};
+        return reg ? basic_handle<const entity_type>{*reg, entt} : basic_handle<const entity_type>{};
     }
 
     /**
@@ -79,7 +69,7 @@ struct basic_handle {
      * @brief Checks if a handle refers to non-null registry pointer and entity.
      * @return True if the handle refers to non-null registry and entity, false otherwise.
      */
-    [[nodiscard]] explicit operator bool() const {
+    [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
         return reg && entt != null;
     }
 
@@ -92,16 +82,16 @@ struct basic_handle {
     }
 
     /**
-     * @brief Returns a pointer to the underlying registry.
-     * @return A pointer to the underlying registry.
+     * @brief Returns a pointer to the underlying registry, if any.
+     * @return A pointer to the underlying registry, if any.
      */
-    [[nodiscard]] registry_type  * registry() const ENTT_NOEXCEPT {
+    [[nodiscard]] registry_type * registry() const ENTT_NOEXCEPT {
         return reg;
     }
 
     /**
      * @brief Returns the entity associated with a handle.
-     * @param value he entity associated with the handle.
+     * @return The entity associated with the handle.
      */
     [[nodiscard]] entity_type entity() const ENTT_NOEXCEPT {
         return entt;
@@ -164,9 +154,9 @@ struct basic_handle {
      * @sa basic_registry::remove
      * @tparam Component Types of components to remove.
      */
-    template<typename... Components>
+    template<typename... Component>
     void remove() const {
-        reg->template remove<Components...>(entt);
+        reg->template remove<Component...>(entt);
     }
 
     /**
@@ -175,9 +165,9 @@ struct basic_handle {
      * @tparam Component Types of components to remove.
      * @return The number of components actually removed.
      */
-    template<typename... Components>
+    template<typename... Component>
     decltype(auto) remove_if_exists() const {
-        return reg->template remove_if_exists<Components...>(entt);
+        return reg->template remove_if_exists<Component...>(entt);
     }
 
     /**
@@ -194,9 +184,9 @@ struct basic_handle {
      * @tparam Component Components for which to perform the check.
      * @return True if the handle has all the components, false otherwise.
      */
-    template<typename... Components>
+    template<typename... Component>
     [[nodiscard]] decltype(auto) has() const {
-        return reg->template has<Components...>(entt);
+        return reg->template has<Component...>(entt);
     }
 
     /**
@@ -206,9 +196,9 @@ struct basic_handle {
      * @return True if the handle has at least one of the given components,
      * false otherwise.
      */
-    template<typename... Components>
+    template<typename... Component>
     [[nodiscard]] decltype(auto) any() const {
-        return reg->template any<Components...>(entt);
+        return reg->template any<Component...>(entt);
     }
 
     /**
@@ -217,9 +207,9 @@ struct basic_handle {
      * @tparam Component Types of components to get.
      * @return References to the components owned by the handle.
      */
-    template<typename... Components>
+    template<typename... Component>
     [[nodiscard]] decltype(auto) get() const {
-        return reg->template get<Components...>(entt);
+        return reg->template get<Component...>(entt);
     }
 
     /**
@@ -241,9 +231,9 @@ struct basic_handle {
      * @tparam Component Types of components to get.
      * @return Pointers to the components owned by the handle.
      */
-    template<typename... Components>
+    template<typename... Component>
     [[nodiscard]] decltype(auto) try_get() const {
-        return reg->template try_get<Components...>(entt);
+        return reg->template try_get<Component...>(entt);
     }
 
     /**
@@ -266,11 +256,26 @@ struct basic_handle {
     }
 
 private:
-    registry_type  *reg;
+    registry_type *reg;
     entity_type entt;
 };
 
 
+/**
+ * @brief Compares two handles.
+ * @tparam Type A valid entity type (see entt_traits for more details).
+ * @tparam Other A valid entity type (see entt_traits for more details).
+ * @param lhs A valid handle.
+ * @param rhs A valid handle.
+ * @return False if both handles refer to the same registry and the same
+ * entity, true otherwise.
+ */
+template<typename Type, typename Other>
+bool operator!=(const basic_handle<Type> &lhs, const basic_handle<Other> &rhs) ENTT_NOEXCEPT {
+    return !(lhs == rhs);
+}
+
+
 /**
  * @brief Deduction guide.
  * @tparam Entity A valid entity type (see entt_traits for more details).

+ 39 - 100
test/entt/entity/handle.cpp

@@ -40,137 +40,76 @@ TEST(BasicHandle, Construction) {
     static_assert(std::is_same_v<const entt::registry *, decltype(chandle.registry())>);
 }
 
-
 TEST(BasicHandle, Invalidation) {
     entt::handle handle;
 
-    ASSERT_TRUE(nullptr == handle.registry());
-    ASSERT_TRUE(entt::null == handle.entity());
     ASSERT_FALSE(handle);
+    ASSERT_EQ(handle.registry(), nullptr);
+    ASSERT_EQ(handle.entity(), entt::entity{entt::null});
 
     entt::registry registry;
     const auto entity = registry.create();
 
-    handle = {registry, entity};
+    handle = { registry, entity };
 
-    ASSERT_FALSE(nullptr == handle.registry());
-    ASSERT_FALSE(entt::null == handle.entity());
     ASSERT_TRUE(handle);
+    ASSERT_NE(handle.registry(), nullptr);
+    ASSERT_NE(handle.entity(), entt::entity{entt::null});
 
     handle = {};
 
-    ASSERT_TRUE(nullptr == handle.registry());
-    ASSERT_TRUE(entt::null == handle.entity());
     ASSERT_FALSE(handle);
+    ASSERT_EQ(handle.registry(), nullptr);
+    ASSERT_EQ(handle.entity(), entt::entity{entt::null});
 }
 
-
 TEST(BasicHandle, Comparison) {
     entt::registry registry;
-    const auto entity1 = registry.create();
-    const auto entity2 = registry.create();
-
-    entt::handle handle1{registry, entity1};
-    entt::handle handle2{registry, entity2};
-    entt::const_handle chandle1 = handle1;
-    entt::const_handle chandle2 = handle2;
-
-    ASSERT_NE(handle1, handle2);
-    ASSERT_FALSE(handle1 == handle2);
-    ASSERT_TRUE(handle1 != handle2);
-
-    ASSERT_NE(chandle1, chandle2);
-    ASSERT_FALSE(chandle1 == chandle2);
-    ASSERT_TRUE(chandle1 != chandle2);
-
-    ASSERT_EQ(handle1, chandle1);
-    ASSERT_TRUE(handle1 == chandle1);
-    ASSERT_FALSE(handle1 != chandle1);
-
-    ASSERT_EQ(handle2, chandle2);
-    ASSERT_TRUE(handle2 == chandle2);
-    ASSERT_FALSE(handle2 != chandle2);
-
-    ASSERT_NE(handle1, chandle2);
-    ASSERT_FALSE(handle1 == chandle2);
-    ASSERT_TRUE(handle1 != chandle2);
-
-    handle1 = {};
-    chandle2 = {};
-
-    ASSERT_NE(handle1, handle2);
-    ASSERT_FALSE(handle1 == handle2);
-    ASSERT_TRUE(handle1 != handle2);
-
-    ASSERT_NE(chandle1, chandle2);
-    ASSERT_FALSE(chandle1 == chandle2);
-    ASSERT_TRUE(chandle1 != chandle2);
-
-    ASSERT_NE(handle1, chandle1);
-    ASSERT_FALSE(handle1 == chandle1);
-    ASSERT_TRUE(handle1 != chandle1);
-
-    ASSERT_NE(handle2, chandle2);
-    ASSERT_FALSE(handle2 == chandle2);
-    ASSERT_TRUE(handle2 != chandle2);
-
-    ASSERT_EQ(handle1, chandle2);
-    ASSERT_TRUE(handle1 == chandle2);
-    ASSERT_FALSE(handle1 != chandle2);
-
-    handle2 = {};
-    chandle1 = {};
-
-    ASSERT_EQ(handle1, handle2);
-    ASSERT_TRUE(handle1 == handle2);
-    ASSERT_FALSE(handle1 != handle2);
+    const auto entity = registry.create();
 
-    ASSERT_EQ(chandle1, chandle2);
-    ASSERT_TRUE(chandle1 == chandle2);
-    ASSERT_FALSE(chandle1 != chandle2);
+    entt::handle handle{registry, entity};
+    entt::const_handle chandle = handle;
 
-    ASSERT_EQ(handle1, chandle1);
-    ASSERT_TRUE(handle1 == chandle1);
-    ASSERT_FALSE(handle1 != chandle1);
+    ASSERT_NE(handle, entt::handle{});
+    ASSERT_FALSE(handle == entt::handle{});
+    ASSERT_TRUE(handle != entt::handle{});
 
-    ASSERT_EQ(handle2, chandle2);
-    ASSERT_TRUE(handle2 == chandle2);
-    ASSERT_FALSE(handle2 != chandle2);
+    ASSERT_NE(chandle, entt::const_handle{});
+    ASSERT_FALSE(chandle == entt::const_handle{});
+    ASSERT_TRUE(chandle != entt::const_handle{});
 
-    ASSERT_EQ(handle1, chandle2);
-    ASSERT_TRUE(handle1 == chandle2);
-    ASSERT_FALSE(handle1 != chandle2);
+    ASSERT_EQ(handle, chandle);
+    ASSERT_TRUE(handle == chandle);
+    ASSERT_FALSE(handle != chandle);
 
-    entt::registry registry_b;
-    const auto entity_b1 = registry.create();
+    ASSERT_EQ(entt::handle{}, entt::const_handle{});
+    ASSERT_TRUE(entt::handle{} == entt::const_handle{});
+    ASSERT_FALSE(entt::handle{} != entt::const_handle{});
 
-    handle1 = {registry_b, entity_b1};
-    handle2 = {registry, entity1};
-    chandle1 = handle1;
-    chandle2 = handle2;
+    handle = {};
+    chandle = {};
 
-    ASSERT_NE(handle1, handle2);
-    ASSERT_FALSE(handle1 == handle2);
-    ASSERT_TRUE(handle1 != handle2);
+    ASSERT_EQ(handle, entt::handle{});
+    ASSERT_TRUE(handle == entt::handle{});
+    ASSERT_FALSE(handle != entt::handle{});
 
-    ASSERT_NE(chandle1, chandle2);
-    ASSERT_FALSE(chandle1 == chandle2);
-    ASSERT_TRUE(chandle1 != chandle2);
+    ASSERT_EQ(chandle, entt::const_handle{});
+    ASSERT_TRUE(chandle == entt::const_handle{});
+    ASSERT_FALSE(chandle != entt::const_handle{});
 
-    ASSERT_EQ(handle1, chandle1);
-    ASSERT_TRUE(handle1 == chandle1);
-    ASSERT_FALSE(handle1 != chandle1);
+    entt::registry other;
+    const auto entt = other.create();
 
-    ASSERT_EQ(handle2, chandle2);
-    ASSERT_TRUE(handle2 == chandle2);
-    ASSERT_FALSE(handle2 != chandle2);
+    handle = { registry, entity };
+    chandle = { other, entt };
 
-    ASSERT_NE(handle1, chandle2);
-    ASSERT_FALSE(handle1 == chandle2);
-    ASSERT_TRUE(handle1 != chandle2);
+    ASSERT_NE(handle, chandle);
+    ASSERT_FALSE(chandle == handle);
+    ASSERT_TRUE(chandle != handle);
+    ASSERT_EQ(handle.entity(), chandle.entity());
+    ASSERT_NE(handle.registry(), chandle.registry());
 }
 
-
 TEST(BasicHandle, Component) {
     entt::registry registry;
     const auto entity = registry.create();