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);
+}