Selaa lähdekoodia

more on context variables

Michele Caini 7 vuotta sitten
vanhempi
commit
2147436a2a
4 muutettua tiedostoa jossa 60 lisäystä ja 26 poistoa
  1. 1 1
      TODO
  2. 12 6
      docs/entity.md
  3. 28 3
      src/entt/entity/registry.hpp
  4. 19 16
      test/entt/entity/registry.cpp

+ 1 - 1
TODO

@@ -20,5 +20,5 @@
   - each components only return actual component, so shared components are returned only once
 * types defined at runtime that refer to the same compile-time type (but to different pools) are possible, the library is almost there
 * add take functionality, eg registry.take(entity, other); where it takes the entity and all its components from registry and move them to other
+* what about paged pools? vector of fixed-size blocks (ease shared components, multi-ownership, etc).
 * add entity function to views/groups (component -> owner, see sparse sets)
-* what about paged pools? vector of fixed-size blocks

+ 12 - 6
docs/entity.md

@@ -831,8 +831,9 @@ const bool null = (entity == entt::null);
 It is often convenient to assign context variables to a registry, so as to make
 it the only _source of truth_ of an application.<br/>
 This is possible by means of a member function named `set` to use to create a
-context variable from a given type. Later on, `ctx` can be used to retrieve the
-newly created instance and `unset` is there to literally reset it if needed.
+context variable from a given type. Later on, either `ctx` or `try_ctx` can be
+used to retrieve the newly created instance and `unset` is there to literally
+reset it if needed.
 
 Example of use:
 
@@ -840,7 +841,11 @@ Example of use:
 // creates a new context variable initialized with the given values
 registry.set<my_type>(42, 'c');
 
-if(auto *var = registry.ctx<my_type>(); var) {
+// gets the context variable
+const auto &var = registry.ctx<my_type>();
+
+// if in doubts, probe the registry to avoid assertions in case of errors
+if(auto *ptr = registry.try_ctx<my_type>(); var) {
     // uses the context variable associated with a registry, if any
 }
 
@@ -850,9 +855,10 @@ registry.unset<my_type>();
 
 The type of a context variable must be such that it's default constructible and
 can be moved. The `set` member function either creates a new instance of the
-context variable or overwrites an already existing one if any. The `ctx` member
-function returns a pointer to the context variable if it exists, otherwise it
-returns a null pointer. This fits well with the `if` statement with initializer.
+context variable or overwrites an already existing one if any. The `try_ctx`
+member function returns a pointer to the context variable if it exists,
+otherwise it returns a null pointer. This fits well with the `if` statement with
+initializer.
 
 # Views and Groups
 

+ 28 - 3
src/entt/entity/registry.hpp

@@ -1645,7 +1645,7 @@ public:
      * registry, a null pointer otherwise.
      */
     template<typename Type>
-    const Type * ctx() const ENTT_NOEXCEPT {
+    const Type * try_ctx() const ENTT_NOEXCEPT {
         const auto ctype = runtime_type<Type, context_family>();
 
         if constexpr(is_named_type_v<Type>) {
@@ -1660,10 +1660,35 @@ public:
         }
     }
 
+    /*! @copydoc try_ctx */
+    template<typename Type>
+    inline Type * try_ctx() ENTT_NOEXCEPT {
+        return const_cast<Type *>(std::as_const(*this).template try_ctx<Type>());
+    }
+
+    /**
+     * @brief Returns a reference to an object in the context of the registry.
+     *
+     * @warning
+     * Attempting to get a context variable that doesn't exist results in
+     * undefined behavior.<br/>
+     * An assertion will abort the execution at runtime in debug mode in case of
+     * invalid requests.
+     *
+     * @tparam Type Type of object to get.
+     * @return A valid reference to the object in the context of the registry.
+     */
+    template<typename Type>
+    const Type & ctx() const ENTT_NOEXCEPT {
+        const auto *instance = try_ctx<Type>();
+        assert(instance);
+        return *instance;
+    }
+
     /*! @copydoc ctx */
     template<typename Type>
-    Type * ctx() ENTT_NOEXCEPT {
-        return const_cast<Type *>(std::as_const(*this).template ctx<Type>());
+    inline Type & ctx() ENTT_NOEXCEPT {
+        return const_cast<Type &>(std::as_const(*this).template ctx<Type>());
     }
 
 private:

+ 19 - 16
test/entt/entity/registry.cpp

@@ -35,42 +35,45 @@ struct listener {
 TEST(Registry, Context) {
     entt::registry registry;
 
-    ASSERT_EQ(registry.ctx<char>(), nullptr);
-    ASSERT_EQ(registry.ctx<int>(), nullptr);
-    ASSERT_EQ(registry.ctx<double>(), nullptr);
+    ASSERT_EQ(registry.try_ctx<char>(), nullptr);
+    ASSERT_EQ(registry.try_ctx<int>(), nullptr);
+    ASSERT_EQ(registry.try_ctx<double>(), nullptr);
 
     registry.set<char>();
     registry.set<int>();
     registry.set<double>();
 
-    ASSERT_NE(registry.ctx<char>(), nullptr);
-    ASSERT_NE(registry.ctx<int>(), nullptr);
-    ASSERT_NE(registry.ctx<double>(), nullptr);
+    ASSERT_NE(registry.try_ctx<char>(), nullptr);
+    ASSERT_NE(registry.try_ctx<int>(), nullptr);
+    ASSERT_NE(registry.try_ctx<double>(), nullptr);
 
     registry.unset<int>();
     registry.unset<double>();
 
-    ASSERT_NE(registry.ctx<char>(), nullptr);
-    ASSERT_EQ(registry.ctx<int>(), nullptr);
-    ASSERT_EQ(registry.ctx<double>(), nullptr);
+    ASSERT_NE(registry.try_ctx<char>(), nullptr);
+    ASSERT_EQ(registry.try_ctx<int>(), nullptr);
+    ASSERT_EQ(registry.try_ctx<double>(), nullptr);
 
     registry.set<char>('c');
     registry.set<int>(42);
     registry.set<double>(1.);
 
-    ASSERT_EQ(*registry.ctx<char>(), 'c');
-    ASSERT_NE(registry.ctx<char>(), nullptr);
+    ASSERT_EQ(registry.ctx<char>(), 'c');
+    ASSERT_NE(registry.try_ctx<char>(), nullptr);
+    ASSERT_EQ(registry.try_ctx<char>(), &registry.ctx<char>());
     ASSERT_EQ(registry.ctx<char>(), std::as_const(registry).ctx<char>());
 
-    ASSERT_EQ(*registry.ctx<int>(), 42);
-    ASSERT_NE(registry.ctx<int>(), nullptr);
+    ASSERT_EQ(registry.ctx<int>(), 42);
+    ASSERT_NE(registry.try_ctx<int>(), nullptr);
+    ASSERT_EQ(registry.try_ctx<int>(), &registry.ctx<int>());
     ASSERT_EQ(registry.ctx<int>(), std::as_const(registry).ctx<int>());
 
-    ASSERT_EQ(*registry.ctx<double>(), 1.);
-    ASSERT_NE(registry.ctx<double>(), nullptr);
+    ASSERT_EQ(registry.ctx<double>(), 1.);
+    ASSERT_NE(registry.try_ctx<double>(), nullptr);
+    ASSERT_EQ(registry.try_ctx<double>(), &registry.ctx<double>());
     ASSERT_EQ(registry.ctx<double>(), std::as_const(registry).ctx<double>());
 
-    ASSERT_EQ(registry.ctx<float>(), nullptr);
+    ASSERT_EQ(registry.try_ctx<float>(), nullptr);
 }
 
 TEST(Registry, Types) {