diff --git a/TODO b/TODO index 6f8acfdd1..105f203fd 100644 --- a/TODO +++ b/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 diff --git a/docs/signal.md b/docs/signal.md index a6b6fee94..b923a1881 100644 --- a/docs/signal.md +++ b/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).
-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.
+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 diff --git a/src/entt/signal/delegate.hpp b/src/entt/signal/delegate.hpp index c30906724..09b5c9979 100644 --- a/src/entt/signal/delegate.hpp +++ b/src/entt/signal/delegate.hpp @@ -159,11 +159,11 @@ public: static_assert(sizeof(Type) <= sizeof(void *)); static_assert(std::is_trivially_copyable_v); static_assert(std::is_trivially_destructible_v); - static_assert(std::is_invocable_r_v); + static_assert(std::is_invocable_r_v); new (&storage) Type{value_or_instance}; fn = [](storage_type &storage, Args... args) -> Ret { - Type value_or_instance = *reinterpret_cast(&storage); + Type &value_or_instance = *reinterpret_cast(&storage); return std::invoke(Candidate, value_or_instance, args...); }; } diff --git a/test/entt/signal/delegate.cpp b/test/entt/signal/delegate.cpp index fe1e10c41..8a252f28f 100644 --- a/test/entt/signal/delegate.cpp +++ b/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{}); } -TEST(Delegate, CurriedFunction) { +TEST(Delegate, CurriedFunctionByValue) { entt::delegate 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 delegate; + delegate.connect<&curried_function_by_ref>(2); + + ASSERT_TRUE(delegate); + ASSERT_EQ(delegate(), 4); + ASSERT_EQ(delegate(), 8); +}