Просмотр исходного кода

delegate: curried functions can accept linked parameters either by value or by reference

Michele Caini 7 лет назад
Родитель
Сommit
3c9a6ad218
4 измененных файлов с 30 добавлено и 13 удалено
  1. 2 3
      TODO
  2. 9 5
      docs/signal.md
  3. 2 2
      src/entt/signal/delegate.hpp
  4. 17 3
      test/entt/signal/delegate.cpp

+ 2 - 3
TODO

@@ -22,7 +22,6 @@
 * tags revenge: if it's possible, reintroduce them but without a link to entities (see #169 for more details)
 
 Ready to go:
-==> req: ref to value with curried functions
-* add on-the-fly sort functionality (is it possible?)
 * (even more) optimized standard views are possible!
-* induce-respect policy
+* add on-the-fly sort functionality
+* introduce induce-respect policy

+ 9 - 5
docs/signal.md

@@ -229,10 +229,10 @@ As shown previously, it accepts functions having type `void(int)`. However, we
 can do something more in this case, because of how the delegate class is
 implemented internally (that is something that goes beyond the purposes of this
 document).<br/>
-In particular, the delegate accepts also functions having type `void(T, int)`,
-as long as `sizeof(T)` is lower than or equal to `sizeof(void *)`. The first
-parameter is stored directly by the delegate class and passed to the connected
-function when needed.
+In particular, the delegate accepts also functions having type equivalent to
+`void(T &, int)`, as long as `sizeof(T)` is lower than or equal to
+`sizeof(void *)`. The first parameter is stored directly by the delegate class
+and passed to the connected function when needed.
 
 In other terms, this works as well with the above definition:
 
@@ -245,7 +245,11 @@ delegate(42);
 
 In this case, the function `g` is invoked with parameters `'c'` and `42`.
 However, the function type of the delegate is still `void(int)`, mainly because
-this is also the signature of its function call operator.
+this is also the signature of its function call operator.<br/>
+When the curried function gets the linked parameter by reference, it can modify
+it and the new value will be stored in place of the previous one. It's highly
+discouraged to accept the parameter by reference, unless you know exactly what
+you're doing. Prefer accepting it by value if possible.
 
 # Event dispatcher
 

+ 2 - 2
src/entt/signal/delegate.hpp

@@ -159,11 +159,11 @@ public:
         static_assert(sizeof(Type) <= sizeof(void *));
         static_assert(std::is_trivially_copyable_v<Type>);
         static_assert(std::is_trivially_destructible_v<Type>);
-        static_assert(std::is_invocable_r_v<Ret, decltype(Candidate), Type, Args...>);
+        static_assert(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, Args...>);
         new (&storage) Type{value_or_instance};
 
         fn = [](storage_type &storage, Args... args) -> Ret {
-            Type value_or_instance = *reinterpret_cast<Type *>(&storage);
+            Type &value_or_instance = *reinterpret_cast<Type *>(&storage);
             return std::invoke(Candidate, value_or_instance, args...);
         };
     }

+ 17 - 3
test/entt/signal/delegate.cpp

@@ -5,10 +5,15 @@ int delegate_function(const int &i) {
     return i*i;
 }
 
-int curried_function(int i, int j) {
+int curried_function_by_value(int i, int j) {
     return i+j;
 }
 
+int curried_function_by_ref(int &value) {
+    value *= 2;
+    return value;
+}
+
 struct delegate_functor {
     int operator()(int i) {
         return i+i;
@@ -194,10 +199,19 @@ TEST(Delegate, ConstInstance) {
     ASSERT_EQ(delegate, entt::delegate<int(int)>{});
 }
 
-TEST(Delegate, CurriedFunction) {
+TEST(Delegate, CurriedFunctionByValue) {
     entt::delegate<int(int)> delegate;
-    delegate.connect<&curried_function>(3);
+    delegate.connect<&curried_function_by_value>(3);
 
     ASSERT_TRUE(delegate);
     ASSERT_EQ(delegate(1), 4);
 }
+
+TEST(Delegate, CurriedFunctionByRef) {
+    entt::delegate<int()> delegate;
+    delegate.connect<&curried_function_by_ref>(2);
+
+    ASSERT_TRUE(delegate);
+    ASSERT_EQ(delegate(), 4);
+    ASSERT_EQ(delegate(), 8);
+}