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

added support for const instances * to the delegate

Michele Caini 7 жил өмнө
parent
commit
167c174f4d

+ 0 - 1
TODO

@@ -20,5 +20,4 @@
 * destroy overload that accepts a couple of iterators (see create)
 * allow for built-in parallel each if possible
 * add on-the-fly sort functionality (is it possible?)
-* introduce support for const instances * in delegate/sigh if possible
 * add support for composable filters

+ 12 - 8
src/entt/signal/delegate.hpp

@@ -80,17 +80,21 @@ class delegate;
  */
 template<typename Ret, typename... Args>
 class delegate<Ret(Args...)> final {
-    using proto_fn_type = Ret(void *, Args...);
-    using stub_type = std::pair<void *, proto_fn_type *>;
+    using proto_fn_type = Ret(const void *, Args...);
+    using stub_type = std::pair<const void *, proto_fn_type *>;
 
     template<auto Function>
-    static Ret proto(void *, Args... args) {
+    static Ret proto(const void *, Args... args) {
         return std::invoke(Function, args...);
     }
 
-    template<typename Class, auto Member>
-    static Ret proto(void *instance, Args... args) {
-        return std::invoke(Member, static_cast<Class *>(instance), args...);
+    template<bool Const, typename Class, auto Member>
+    static Ret proto(const void *instance, Args... args) {
+        if constexpr(Const) {
+            return std::invoke(Member, static_cast<const Class *>(instance), args...);
+        } else {
+            return std::invoke(Member, const_cast<Class *>(static_cast<const Class *>(instance)), args...);
+        }
     }
 
 public:
@@ -150,7 +154,7 @@ public:
     template<auto Member, typename Class>
     void connect(Class *instance) ENTT_NOEXCEPT {
         static_assert(std::is_invocable_r_v<Ret, decltype(Member), Class, Args...>);
-        stub = std::make_pair(instance, &proto<Class, Member>);
+        stub = std::make_pair(instance, &proto<std::is_const_v<Class>, std::remove_const_t<Class>, Member>);
     }
 
     /**
@@ -159,7 +163,7 @@ public:
      * After a reset, a delegate can be safely invoked with no effect.
      */
     void reset() ENTT_NOEXCEPT {
-        stub.second = nullptr;
+        stub = std::make_pair(nullptr, nullptr);
     }
 
     /**

+ 31 - 0
test/entt/signal/delegate.cpp

@@ -9,6 +9,10 @@ struct delegate_functor {
     int operator()(int i) {
         return i+i;
     }
+
+    int identity(int i) const {
+        return i;
+    }
 };
 
 struct const_nonconst_noexcept {
@@ -43,7 +47,17 @@ TEST(Delegate, Functionalities) {
     ASSERT_TRUE(mfdel);
 
     ASSERT_EQ(ffdel, entt::delegate<int(int)>{});
+    ASSERT_NE(mfdel, entt::delegate<int(int)>{});
     ASSERT_NE(ffdel, mfdel);
+
+    mfdel.reset();
+
+    ASSERT_FALSE(ffdel);
+    ASSERT_FALSE(mfdel);
+
+    ASSERT_EQ(ffdel, entt::delegate<int(int)>{});
+    ASSERT_EQ(mfdel, entt::delegate<int(int)>{});
+    ASSERT_EQ(ffdel, mfdel);
 }
 
 TEST(Delegate, Comparison) {
@@ -109,3 +123,20 @@ TEST(Delegate, DeducedGuidelines) {
     ASSERT_TRUE(member_h_deduced);
     ASSERT_TRUE(member_i_deduced);
 }
+
+TEST(Delegate, ConstInstance) {
+    entt::delegate<int(int)> delegate;
+    const delegate_functor functor;
+
+    ASSERT_FALSE(delegate);
+
+    delegate.connect<&delegate_functor::identity>(&functor);
+
+    ASSERT_TRUE(delegate);
+    ASSERT_EQ(delegate(3), 3);
+
+    delegate.reset();
+
+    ASSERT_FALSE(delegate);
+    ASSERT_EQ(delegate, entt::delegate<int(int)>{});
+}

+ 9 - 6
test/entt/signal/sigh.cpp

@@ -232,20 +232,23 @@ TEST(SigH, Collector) {
 TEST(SigH, ConstNonConstNoExcept) {
     entt::sigh<void()> sigh;
     const_nonconst_noexcept functor;
+    const const_nonconst_noexcept cfunctor;
 
     sigh.sink().connect<&const_nonconst_noexcept::f>(&functor);
     sigh.sink().connect<&const_nonconst_noexcept::g>(&functor);
-    sigh.sink().connect<&const_nonconst_noexcept::h>(&functor);
-    sigh.sink().connect<&const_nonconst_noexcept::i>(&functor);
+    sigh.sink().connect<&const_nonconst_noexcept::h>(&cfunctor);
+    sigh.sink().connect<&const_nonconst_noexcept::i>(&cfunctor);
     sigh.publish();
 
-    ASSERT_EQ(functor.cnt, 4);
+    ASSERT_EQ(functor.cnt, 2);
+    ASSERT_EQ(cfunctor.cnt, 2);
 
     sigh.sink().disconnect<&const_nonconst_noexcept::f>(&functor);
     sigh.sink().disconnect<&const_nonconst_noexcept::g>(&functor);
-    sigh.sink().disconnect<&const_nonconst_noexcept::h>(&functor);
-    sigh.sink().disconnect<&const_nonconst_noexcept::i>(&functor);
+    sigh.sink().disconnect<&const_nonconst_noexcept::h>(&cfunctor);
+    sigh.sink().disconnect<&const_nonconst_noexcept::i>(&cfunctor);
     sigh.publish();
 
-    ASSERT_EQ(functor.cnt, 4);
+    ASSERT_EQ(functor.cnt, 2);
+    ASSERT_EQ(cfunctor.cnt, 2);
 }