瀏覽代碼

sigh: filter out null opaque pointers

Michele Caini 6 年之前
父節點
當前提交
bea6f3ec14
共有 2 個文件被更改,包括 47 次插入15 次删除
  1. 24 15
      src/entt/signal/sigh.hpp
  2. 23 0
      test/entt/signal/sigh.cpp

+ 24 - 15
src/entt/signal/sigh.hpp

@@ -339,11 +339,13 @@ public:
      */
     template<auto Function>
     sink before() {
-        sink other{*this};
-        auto &calls = signal->calls;
         delegate<Ret(Args...)> call{};
         call.template connect<Function>();
+
+        const auto &calls = signal->calls;
         const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
+
+        sink other{*this};
         other.offset = std::distance(it, calls.cend());
         return other;
     }
@@ -358,11 +360,13 @@ public:
      */
     template<auto Candidate, typename Type>
     sink before(Type &value_or_instance) {
-        sink other{*this};
-        auto &calls = signal->calls;
         delegate<Ret(Args...)> call{};
         call.template connect<Candidate>(value_or_instance);
+
+        const auto &calls = signal->calls;
         const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
+
+        sink other{*this};
         other.offset = std::distance(it, calls.cend());
         return other;
     }
@@ -387,12 +391,16 @@ public:
      */
     sink before(const void *value_or_instance) {
         sink other{*this};
-        auto &calls = signal->calls;
-        const auto it = std::find_if(calls.cbegin(), calls.cend(), [value_or_instance](const auto &delegate) {
-            return delegate.instance() == value_or_instance;
-        });
 
-        other.offset = std::distance(it, calls.cend());
+        if(value_or_instance) {
+            const auto &calls = signal->calls;
+            const auto it = std::find_if(calls.cbegin(), calls.cend(), [value_or_instance](const auto &delegate) {
+                return delegate.instance() == value_or_instance;
+            });
+
+            other.offset = std::distance(it, calls.cend());
+        }
+
         return other;
     }
 
@@ -402,8 +410,7 @@ public:
      */
     sink before() {
         sink other{*this};
-        auto &calls = signal->calls;
-        other.offset = std::distance(calls.cbegin(), calls.cend());
+        other.offset = signal->calls.size();
         return other;
     }
 
@@ -503,10 +510,12 @@ public:
      * @param value_or_instance An opaque pointer that fits the purpose.
      */
     void disconnect(const void *value_or_instance) {
-        auto &calls = signal->calls;
-        calls.erase(std::remove_if(calls.begin(), calls.end(), [value_or_instance](const auto &delegate) {
-            return delegate.instance() == value_or_instance;
-        }), calls.end());
+        if(value_or_instance) {
+            auto &calls = signal->calls;
+            calls.erase(std::remove_if(calls.begin(), calls.end(), [value_or_instance](const auto &delegate) {
+                return delegate.instance() == value_or_instance;
+            }), calls.end());
+        }
     }
 
     /*! @brief Disconnects all the listeners from a signal. */

+ 23 - 0
test/entt/signal/sigh.cpp

@@ -64,6 +64,11 @@ TEST_F(SigH, Clear) {
     ASSERT_FALSE(sink.empty());
     ASSERT_FALSE(sigh.empty());
 
+    sink.disconnect(nullptr);
+
+    ASSERT_FALSE(sink.empty());
+    ASSERT_FALSE(sigh.empty());
+
     sink.disconnect();
 
     ASSERT_TRUE(sink.empty());
@@ -166,6 +171,11 @@ TEST_F(SigH, Members) {
     ASSERT_FALSE(sigh.empty());
     ASSERT_EQ(2u, sigh.size());
 
+    sink.disconnect(nullptr);
+
+    ASSERT_FALSE(sigh.empty());
+    ASSERT_EQ(2u, sigh.size());
+
     sink.disconnect(l1);
 
     ASSERT_FALSE(sigh.empty());
@@ -403,6 +413,19 @@ TEST_F(SigH, BeforeOpaqueInstanceOrPayload) {
     ASSERT_EQ(functor.value, 6);
 }
 
+TEST_F(SigH, BeforeNullOpaqueInstanceOrPayload) {
+    entt::sigh<void(int)> sigh;
+    entt::sink sink{sigh};
+    before_after functor;
+
+    sink.connect<&before_after::static_mul>(functor);
+    sink.connect<&before_after::add>(functor);
+    sink.before(nullptr).connect<&before_after::static_add>();
+    sigh.publish(2);
+
+    ASSERT_EQ(functor.value, 4);
+}
+
 TEST_F(SigH, BeforeAnythingElse) {
     entt::sigh<void(int)> sigh;
     entt::sink sink{sigh};