diff --git a/include/etl/private/delegate_cpp11.h b/include/etl/private/delegate_cpp11.h index ebac92f74..b3124e766 100644 --- a/include/etl/private/delegate_cpp11.h +++ b/include/etl/private/delegate_cpp11.h @@ -54,6 +54,11 @@ Original publication: https://www.codeproject.com/Articles/1170503/The-Impossibl #include "../type_traits.h" #include "../utility.h" #include "../optional.h" +#include "../functional.h" +#if ETL_USING_STL +#include +#endif +#include namespace etl { @@ -111,21 +116,117 @@ namespace etl //************************************************************************* // Construct from lambda or functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, bool> = true> + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && (alignof(TLambda) <= alignof(void*)) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> ETL_CONSTEXPR14 delegate(TLambda& instance) { - assign((void*)(&instance), lambda_stub); + assign_lambda(instance, lambda_object_stub); + } + + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(etl::reference_wrapper& instance) + { + assign((void*)(&instance.get()), lambda_stub); + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(std::reference_wrapper& instance) + { + assign((void*)(&instance.get()), lambda_stub); + } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(TLambda& instance) = delete; + + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && (alignof(TLambda) <= alignof(void*)) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(TLambda&& instance) + { + assign_lambda(etl::forward(instance), lambda_object_stub); + } + + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(etl::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), lambda_stub); + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(std::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), lambda_stub); } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(TLambda&& instance) = delete; //************************************************************************* // Construct from const lambda or functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, bool> = true> + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && (alignof(TLambda) <= alignof(void*)) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> ETL_CONSTEXPR14 delegate(const TLambda& instance) { - assign((void*)(&instance), const_lambda_stub); + assign_lambda(instance, const_lambda_object_stub); + } + + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(etl::reference_wrapper& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(std::reference_wrapper& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(const TLambda& instance) = delete; + + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && (alignof(TLambda) <= alignof(void*)) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(const TLambda&& instance) + { + assign_lambda(etl::forward(instance), const_lambda_object_stub); } + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(etl::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(std::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate(const TLambda&& instance) = delete; + //************************************************************************* /// Create from function (Compile time). //************************************************************************* @@ -235,21 +336,117 @@ namespace etl //************************************************************************* /// Set from Lambda or Functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, bool> = true> + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && (alignof(TLambda) <= alignof(void*)) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> ETL_CONSTEXPR14 void set(TLambda& instance) { - assign((void*)(&instance), lambda_stub); + assign_lambda(instance, lambda_object_stub); + } + + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(etl::reference_wrapper& instance) + { + assign((void*)(&instance.get()), lambda_stub); + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(std::reference_wrapper& instance) + { + assign((void*)(&instance.get()), lambda_stub); } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(TLambda& instance) = delete; + + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && (alignof(TLambda) <= alignof(void*)) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(TLambda&& instance) + { + assign_lambda(etl::forward(instance), lambda_object_stub); + } + + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(etl::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), lambda_stub); + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(std::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), lambda_stub); + } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(TLambda&& instance) = delete; //************************************************************************* /// Set from const Lambda or Functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, bool> = true> + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && (alignof(TLambda) <= alignof(void*)) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> ETL_CONSTEXPR14 void set(const TLambda& instance) { - assign((void*)(&instance), const_lambda_stub); + assign_lambda(instance, const_lambda_object_stub); + } + + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(etl::reference_wrapper& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(std::reference_wrapper& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(const TLambda& instance) = delete; + + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && etl::is_trivially_copyable::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(const TLambda&& instance) + { + assign_lambda(etl::forward(instance), const_lambda_object_stub); } + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(etl::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(std::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 void set(const TLambda&& instance) = delete; + //************************************************************************* /// Set from instance method (Run time). //************************************************************************* @@ -383,23 +580,129 @@ namespace etl //************************************************************************* /// Create from Lambda or Functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, bool> = true> + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && (alignof(TLambda) <= alignof(void*)) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> ETL_CONSTEXPR14 delegate& operator =(TLambda& instance) { - assign((void*)(&instance), lambda_stub); + assign_lambda(instance, lambda_object_stub); + return *this; + } + + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(etl::reference_wrapper& instance) + { + assign((void*)(&instance.get()), lambda_stub); + return *this; + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(std::reference_wrapper& instance) + { + assign((void*)(&instance.get()), lambda_stub); + return *this; + } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(TLambda& instance) = delete; + + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && (alignof(TLambda) <= alignof(void*)) && etl::is_trivially_copyable::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(TLambda&& instance) + { + assign_lambda(etl::forward(instance), lambda_object_stub); + return *this; + } + + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(etl::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), lambda_stub); + return *this; + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(std::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), lambda_stub); return *this; } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(TLambda&& instance) = delete; //************************************************************************* /// Create from const Lambda or Functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, bool> = true> + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && (alignof(TLambda) <= alignof(void*)) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> ETL_CONSTEXPR14 delegate& operator =(const TLambda& instance) { - assign((void*)(&instance), const_lambda_stub); + assign_lambda(instance, const_lambda_object_stub); return *this; } + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(etl::reference_wrapper& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + return *this; + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(std::reference_wrapper& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + return *this; + } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(const TLambda& instance) = delete; + + template ::value + && ((sizeof(TLambda) <= sizeof(void*)) && (alignof(TLambda) <= alignof(void*)) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(const TLambda&& instance) + { + assign_lambda(etl::forward(instance), const_lambda_object_stub); + return *this; + } + + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(etl::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + return *this; + } + +#if ETL_USING_STL + template ::value && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(std::reference_wrapper&& instance) + { + assign((void*)(&instance.get()), const_lambda_stub); + return *this; + } +#endif + + template ::value + && (((sizeof(TLambda) > sizeof(void*)) || (alignof(TLambda) > alignof(void*))) && etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + && !etl::is_same, TLambda>::value, bool> = true> + ETL_CONSTEXPR14 delegate& operator =(const TLambda&& instance) = delete; + //************************************************************************* /// Checks equality. //************************************************************************* @@ -434,8 +737,20 @@ namespace etl } private: + struct lambda_tag {}; + + union object_type { + void* pointer; + alignas(void*) char buffer[sizeof(void*)]; - using stub_type = TReturn(*)(void* object, TParams...); + ETL_CONSTEXPR14 object_type() : pointer{nullptr} {} // None constructor + ETL_CONSTEXPR14 object_type(void* ptr) : pointer {ptr} {} // object pointer + template + ETL_CONSTEXPR14 object_type(lambda_tag, T&& object) : buffer{0, } { new (&this->buffer[0]) T(etl::forward(object)); } + + ~object_type() = default; + }; + using stub_type = TReturn(*)(object_type object, TParams...); //************************************************************************* /// The internal invocation object. @@ -445,7 +760,7 @@ namespace etl invocation_element() = default; //*********************************************************************** - ETL_CONSTEXPR14 invocation_element(void* object_, stub_type stub_) + ETL_CONSTEXPR14 invocation_element(object_type object_, stub_type stub_) : object(object_) , stub(stub_) { @@ -454,13 +769,13 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 bool operator ==(const invocation_element& rhs) const { - return (rhs.stub == stub) && (rhs.object == object); + return (rhs.stub == stub) && (std::memcmp(&rhs.object, &object, sizeof(object)) == 0); } //*********************************************************************** ETL_CONSTEXPR14 bool operator !=(const invocation_element& rhs) const { - return (rhs.stub != stub) || (rhs.object != object); + return (rhs.stub != stub) || (std::memcmp(&rhs.object, &object, sizeof(object)) != 0); } //*********************************************************************** @@ -471,14 +786,14 @@ namespace etl } //*********************************************************************** - void* object = ETL_NULLPTR; - stub_type stub = ETL_NULLPTR; + object_type object {}; + stub_type stub = ETL_NULLPTR; }; //************************************************************************* /// Constructs a delegate from an object and stub. //************************************************************************* - ETL_CONSTEXPR14 delegate(void* object, stub_type stub) + ETL_CONSTEXPR14 delegate(object_type object, stub_type stub) : invocation(object, stub) { } @@ -500,13 +815,27 @@ namespace etl invocation.stub = stub; } + template + ETL_CONSTEXPR14 void assign_lambda(T&& object, stub_type stub) + { + invocation.object = object_type(lambda_tag{}, etl::forward(object)); + invocation.stub = stub; + } + + template + ETL_CONSTEXPR14 void assign_lambda(T& object, stub_type stub) + { + invocation.object = object_type(lambda_tag{}, object); + invocation.stub = stub; + } + //************************************************************************* /// Stub call for a member function. Run time instance. //************************************************************************* template - static ETL_CONSTEXPR14 TReturn method_stub(void* object, TParams... params) + static ETL_CONSTEXPR14 TReturn method_stub(object_type object, TParams... params) { - T* p = static_cast(object); + T* p = static_cast(object.pointer); return (p->*Method)(etl::forward(params)...); } @@ -514,9 +843,9 @@ namespace etl /// Stub call for a const member function. Run time instance. //************************************************************************* template - static ETL_CONSTEXPR14 TReturn const_method_stub(void* object, TParams... params) + static ETL_CONSTEXPR14 TReturn const_method_stub(object_type object, TParams... params) { - T* const p = static_cast(object); + T* const p = static_cast(object.pointer); return (p->*Method)(etl::forward(params)...); } @@ -524,7 +853,7 @@ namespace etl /// Stub call for a member function. Compile time instance. //************************************************************************* template - static ETL_CONSTEXPR14 TReturn method_instance_stub(void*, TParams... params) + static ETL_CONSTEXPR14 TReturn method_instance_stub(object_type, TParams... params) { return (Instance.*Method)(etl::forward(params)...); } @@ -533,7 +862,7 @@ namespace etl /// Stub call for a const member function. Compile time instance. //************************************************************************* template - static ETL_CONSTEXPR14 TReturn const_method_instance_stub(void*, TParams... params) + static ETL_CONSTEXPR14 TReturn const_method_instance_stub(object_type, TParams... params) { return (Instance.*Method)(etl::forward(params)...); } @@ -543,7 +872,7 @@ namespace etl /// Stub call for a function operator. Compile time instance. //************************************************************************* template - static ETL_CONSTEXPR14 TReturn operator_instance_stub(void*, TParams... params) + static ETL_CONSTEXPR14 TReturn operator_instance_stub(object_type, TParams... params) { return Instance.operator()(etl::forward(params)...); } @@ -553,7 +882,7 @@ namespace etl /// Stub call for a free function. //************************************************************************* template - static ETL_CONSTEXPR14 TReturn function_stub(void*, TParams... params) + static ETL_CONSTEXPR14 TReturn function_stub(object_type, TParams... params) { return (Method)(etl::forward(params)...); } @@ -562,22 +891,36 @@ namespace etl /// Stub call for a lambda or functor function. //************************************************************************* template - static ETL_CONSTEXPR14 TReturn lambda_stub(void* object, TParams... arg) + static ETL_CONSTEXPR14 TReturn lambda_stub(object_type object, TParams... arg) { - TLambda* p = static_cast(object); + TLambda* p = static_cast(object.pointer); return (p->operator())(etl::forward(arg)...); } + template + static ETL_CONSTEXPR14 TReturn lambda_object_stub(object_type object, TParams... arg) + { + TLambda& p = *reinterpret_cast(&object.buffer); + return (p.operator())(etl::forward(arg)...); + } + //************************************************************************* /// Stub call for a const lambda or functor function. //************************************************************************* template - static ETL_CONSTEXPR14 TReturn const_lambda_stub(void* object, TParams... arg) + static ETL_CONSTEXPR14 TReturn const_lambda_stub(object_type object, TParams... arg) { - const TLambda* p = static_cast(object); + const TLambda* p = static_cast(object.pointer); return (p->operator())(etl::forward(arg)...); } + template + static ETL_CONSTEXPR14 TReturn const_lambda_object_stub(object_type object, TParams... arg) + { + const TLambda& p = *reinterpret_cast(&object.buffer); + return (p.operator())(etl::forward(arg)...); + } + //************************************************************************* /// The invocation object. //************************************************************************* diff --git a/test/test_callback_timer_interrupt.cpp b/test/test_callback_timer_interrupt.cpp index cbc7d5dd3..78e07f9ef 100644 --- a/test/test_callback_timer_interrupt.cpp +++ b/test/test_callback_timer_interrupt.cpp @@ -803,13 +803,13 @@ namespace timer_log.push_back(TimerLogEntry{ 3, timer_count }); }; - callback_type delegate_callback0(dc0); + callback_type delegate_callback0(etl::ref(dc0)); - callback_type delegate_callback1(dc1); + callback_type delegate_callback1(etl::ref(dc1)); - callback_type delegate_callback2(dc2); + callback_type delegate_callback2(etl::ref(dc2)); - callback_type delegate_callback3(dc3); + callback_type delegate_callback3(etl::ref(dc3)); timer_log.clear(); timer_controller.enable(true); diff --git a/test/test_delegate.cpp b/test/test_delegate.cpp index 63ff26482..ce30227a1 100644 --- a/test/test_delegate.cpp +++ b/test/test_delegate.cpp @@ -421,12 +421,32 @@ namespace CHECK(parameter_correct); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_lambda_capture_int) + { + struct CaptureObject { + int i; + int j; + + bool eval(int i_, int j_) const { return (i_ == i) && (j_ == j); } + }; + + CaptureObject co { VALUE1, VALUE2 }; + + etl::delegate d([co](int i, int j) { function_called = FunctionCalled::Lambda_Called; parameter_correct = co.eval(i,j); }); + + d(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Lambda_Called); + CHECK(parameter_correct); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_lambda_int_create) { auto lambda = [](int i, int j) { function_called = FunctionCalled::Lambda_Called; parameter_correct = (i == VALUE1) && (j == VALUE2); }; - etl::delegate d(lambda); + etl::delegate d(etl::ref(lambda)); d(VALUE1, VALUE2); @@ -439,7 +459,7 @@ namespace { Test test; - etl::delegate d(test); + etl::delegate d(etl::ref(test)); d(); @@ -477,7 +497,7 @@ namespace { const Test test; - etl::delegate d(test); + etl::delegate d(etl::ref(test)); d(); @@ -537,7 +557,7 @@ namespace etl::delegate d; - d = test; + d = etl::ref(test); d(); @@ -957,6 +977,29 @@ namespace CHECK(parameter_correct); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_set_lambda_capture_int) + { + etl::delegate d; + + struct CaptureObject { + int i; + int j; + + bool eval(int i_, int j_) const { return (i_ == i) && (j_ == j); } + void assign(int i_, int j_) { this->i = i_; this->j = j_; } + }; + + CaptureObject co { 0, 0 }; + + d.set([&co](int i, int j) { co.assign(i,j); function_called = FunctionCalled::Lambda_Called; parameter_correct = co.eval(i,j); }); + + d(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Lambda_Called); + CHECK(parameter_correct); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_set_member_reference) { @@ -1194,7 +1237,7 @@ namespace { std::function std_function(free_int); - etl::delegate d(std_function); + etl::delegate d(etl::ref(std_function)); d(VALUE1, VALUE2);