124 using object_ptr =
void*;
125 using function_ptr = TReturn (*)(TArgs...);
129 using return_type = TReturn;
130 using argument_types = etl::type_list<TArgs...>;
147 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value,
void>>
148 ETL_CONSTEXPR14
delegate(TLambda& instance) ETL_NOEXCEPT
150 assign(object_ptr(&instance), lambda_stub<TLambda>);
156 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value,
void>>
157 ETL_CONSTEXPR14 delegate(
const TLambda& instance) ETL_NOEXCEPT
159 assign(object_ptr(&instance), const_lambda_stub<TLambda>);
166 template <
typename TLambda,
167 typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TArgs...)>, TLambda>::value
168 && !etl::is_convertible<TLambda, function_ptr>::value,
170 ETL_CONSTEXPR14 delegate(TLambda&& instance) =
delete;
175 delegate(function_ptr fp) ETL_NOEXCEPT
177 assign(fp, function_ptr_stub);
183 template <TReturn (*Method)(TArgs...)>
187 return delegate(function_stub<Method>);
193 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value,
void>>
197 return delegate(object_ptr(&instance), lambda_stub<TLambda>);
203 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value,
void>>
207 return delegate(object_ptr(&instance), const_lambda_stub<TLambda>);
214 static delegate create(function_ptr fp) ETL_NOEXCEPT
216 return delegate(fp, function_ptr_stub);
222 template <
typename T, TReturn (T::*Method)(TArgs...)>
226 return delegate(object_ptr(&instance), method_stub<T, Method>);
233 template <
typename T, TReturn (T::*Method)(TArgs...)>
240 template <
typename T, TReturn (T::*Method)(TArgs...)
const>
244 return delegate(object_ptr(&instance), const_method_stub<T, Method>);
250 template <
typename T, TReturn (T::*Method)(TArgs...)
const>
256 template <
typename T, T& Instance, TReturn (T::*Method)(TArgs...)>
260 return delegate(method_instance_stub<T, Method, Instance>);
267 template <
typename T, TReturn (T::*Method)(TArgs...), T& Instance>
271 return delegate(method_instance_stub<T, Method, Instance>);
277 template <
typename T, T
const& Instance, TReturn (T::*Method)(TArgs...)
const>
281 return delegate(const_method_instance_stub<T, Method, Instance>);
288 template <
typename T, TReturn (T::*Method)(TArgs...)
const, T
const& Instance>
292 return delegate(const_method_instance_stub<T, Method, Instance>);
295#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
300 template <
typename T, T& Instance>
304 return delegate(operator_instance_stub<T, Instance>);
311 template <TReturn (*Method)(TArgs...)>
312 ETL_CONSTEXPR14
void set() ETL_NOEXCEPT
314 assign(function_stub<Method>);
320 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value,
void>>
321 ETL_CONSTEXPR14
void set(TLambda& instance) ETL_NOEXCEPT
323 assign(object_ptr(&instance), lambda_stub<TLambda>);
329 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value,
void>>
330 ETL_CONSTEXPR14
void set(
const TLambda& instance) ETL_NOEXCEPT
332 assign(object_ptr(&instance), const_lambda_stub<TLambda>);
338 void set(function_ptr fp) ETL_NOEXCEPT
340 assign(fp, function_ptr_stub);
346 template <
typename T, TReturn (T::*Method)(TArgs...)>
347 ETL_CONSTEXPR14
void set(T& instance) ETL_NOEXCEPT
349 assign(object_ptr(&instance), method_stub<T, Method>);
355 template <
typename T, TReturn (T::*Method)(TArgs...)
const>
356 ETL_CONSTEXPR14
void set(T& instance) ETL_NOEXCEPT
358 assign(object_ptr(&instance), const_method_stub<T, Method>);
364 template <
typename T, T& Instance, TReturn (T::*Method)(TArgs...)>
365 ETL_CONSTEXPR14
void set() ETL_NOEXCEPT
367 assign(method_instance_stub<T, Method, Instance>);
374 template <
typename T, TReturn (T::*Method)(TArgs...), T& Instance>
375 ETL_CONSTEXPR14
void set() ETL_NOEXCEPT
377 assign(method_instance_stub<T, Method, Instance>);
383 template <
typename T, T
const& Instance, TReturn (T::*Method)(TArgs...)
const>
384 ETL_CONSTEXPR14
void set() ETL_NOEXCEPT
386 assign(const_method_instance_stub<T, Method, Instance>);
393 template <
typename T, TReturn (T::*Method)(TArgs...)
const, T
const& Instance>
394 ETL_CONSTEXPR14
void set() ETL_NOEXCEPT
396 assign(const_method_instance_stub<T, Method, Instance>);
402 ETL_CONSTEXPR14
void clear() ETL_NOEXCEPT
410 template <
typename... TCallArgs>
411 ETL_CONSTEXPR14 return_type
operator()(TCallArgs&&... args)
const
413 ETL_STATIC_ASSERT((
sizeof...(TCallArgs) ==
sizeof...(TArgs)),
"Incorrect number of parameters passed to delegate");
414 ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
415 "Incompatible parameter types passed to delegate");
419 return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
426 template <
typename TRet = TReturn,
typename... TCallArgs>
427 ETL_CONSTEXPR14
typename etl::enable_if_t<etl::is_same<TRet, void>::value,
bool>
call_if(TCallArgs&&... args)
const
429 ETL_STATIC_ASSERT((
sizeof...(TCallArgs) ==
sizeof...(TArgs)),
"Incorrect number of parameters passed to delegate");
430 ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
431 "Incompatible parameter types passed to delegate");
435 (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
448 template <
typename TRet = TReturn,
typename... TCallArgs>
451 ETL_STATIC_ASSERT((
sizeof...(TCallArgs) ==
sizeof...(TArgs)),
"Incorrect number of parameters passed to delegate");
452 ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
453 "Incompatible parameter types passed to delegate");
459 result = (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
469 template <
typename TAlternative,
typename... TCallArgs>
470 ETL_CONSTEXPR14 TReturn
call_or(TAlternative&& alternative, TCallArgs&&... args)
const
472 ETL_STATIC_ASSERT((
sizeof...(TCallArgs) ==
sizeof...(TArgs)),
"Incorrect number of parameters passed to delegate");
473 ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
474 "Incompatible parameter types passed to delegate");
478 return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
482 return etl::forward<TAlternative>(alternative)(etl::forward<TCallArgs>(args)...);
490 template <TReturn (*Method)(TArgs...),
typename... TCallArgs>
491 ETL_CONSTEXPR14 TReturn
call_or(TCallArgs&&... args)
const
493 ETL_STATIC_ASSERT((
sizeof...(TCallArgs) ==
sizeof...(TArgs)),
"Incorrect number of parameters passed to delegate");
494 ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
495 "Incompatible parameter types passed to delegate");
499 return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
503 return (Method)(etl::forward<TCallArgs>(args)...);
515 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value,
void>>
518 assign(object_ptr(&instance), lambda_stub<TLambda>);
525 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value,
void>>
528 assign(object_ptr(&instance), const_lambda_stub<TLambda>);
535 delegate& operator=(function_ptr fp) ETL_NOEXCEPT
537 assign(fp, function_ptr_stub);
546 return invocation == rhs.invocation;
554 return invocation != rhs.invocation;
560 ETL_NODISCARD ETL_CONSTEXPR14
bool is_valid() const ETL_NOEXCEPT
562 return invocation.stub != ETL_NULLPTR;
568 ETL_NODISCARD ETL_CONSTEXPR14
operator bool() const ETL_NOEXCEPT
579 template <
typename TCallableType,
typename =
void>
584 template <
typename TCallableType>
585 struct is_invocable_with< TCallableType,
etl::void_t<decltype(etl::declval<TCallableType&>()(etl::declval<TArgs>()...))>>
586 :
etl::bool_constant< etl::is_convertible< decltype(etl::declval<TCallableType&>()(etl::declval<TArgs>()...)), TReturn>::value>
590 template <
typename TCallableType,
typename =
void>
595 template <
typename TCallableType>
596 struct is_invocable_with_const< TCallableType, etl::void_t<decltype(etl::declval<const TCallableType&>()(etl::declval<TArgs>()...))>>
597 : etl::bool_constant< etl::is_convertible< decltype(etl::declval<const TCallableType&>()(etl::declval<TArgs>()...)), TReturn>::value>
601 template <
typename TCallableType>
602 struct is_compatible_callable : etl::bool_constant<is_invocable_with<TCallableType>::value || is_invocable_with_const<TCallableType>::value>
609 struct invocation_element
611 using stub_type = TReturn (*)(
const invocation_element&, TArgs...);
614 ETL_CONSTEXPR14 invocation_element() ETL_NOEXCEPT
615 : ptr(object_ptr(ETL_NULLPTR))
621 ETL_CONSTEXPR14 invocation_element(stub_type stub_) ETL_NOEXCEPT
628 ETL_CONSTEXPR14 invocation_element(object_ptr object_, stub_type stub_) ETL_NOEXCEPT
635 ETL_CONSTEXPR14 invocation_element(function_ptr fp_, stub_type stub_) ETL_NOEXCEPT
642 ETL_CONSTEXPR14
bool operator==(
const invocation_element& rhs)
const ETL_NOEXCEPT
644 return (rhs.stub == stub) && ((stub == function_ptr_stub) ? (rhs.ptr.fp == ptr.fp) : (rhs.ptr.object == ptr.object));
648 ETL_CONSTEXPR14
bool operator!=(
const invocation_element& rhs)
const ETL_NOEXCEPT
654 ETL_CONSTEXPR14
void clear() ETL_NOEXCEPT
662 ETL_CONSTEXPR14 ptr_type() ETL_NOEXCEPT
663 : object(ETL_NULLPTR)
667 ETL_CONSTEXPR14 ptr_type(object_ptr object_) ETL_NOEXCEPT
672 ETL_CONSTEXPR14 ptr_type(function_ptr fp_) ETL_NOEXCEPT
685 using stub_type =
typename invocation_element::stub_type;
690 ETL_CONSTEXPR14
delegate(object_ptr
object, stub_type stub) ETL_NOEXCEPT
691 : invocation(
object, stub)
698 ETL_CONSTEXPR14
delegate(function_ptr fp, stub_type stub) ETL_NOEXCEPT
699 : invocation(fp, stub)
706 ETL_CONSTEXPR14 delegate(stub_type stub) ETL_NOEXCEPT
714 ETL_CONSTEXPR14
void assign(object_ptr
object, stub_type stub) ETL_NOEXCEPT
716 invocation.ptr.object = object;
717 invocation.stub = stub;
723 ETL_CONSTEXPR14
void assign(function_ptr fp, stub_type stub) ETL_NOEXCEPT
725 invocation.ptr.fp = fp;
726 invocation.stub = stub;
732 ETL_CONSTEXPR14
void assign(stub_type stub) ETL_NOEXCEPT
734 invocation.ptr.object = ETL_NULLPTR;
735 invocation.stub = stub;
741 template <
typename T, TReturn (T::*Method)(TArgs...)>
742 static ETL_CONSTEXPR14 TReturn method_stub(
const invocation_element& invocation, TArgs... args)
744 T* p =
static_cast<T*
>(invocation.ptr.object);
745 return (p->*Method)(etl::forward<TArgs>(args)...);
751 template <
typename T, TReturn (T::*Method)(TArgs...)
const>
752 static ETL_CONSTEXPR14 TReturn const_method_stub(
const invocation_element& invocation, TArgs... args)
754 T*
const p =
static_cast<T*
>(invocation.ptr.object);
755 return (p->*Method)(etl::forward<TArgs>(args)...);
761 template <
typename T, TReturn (T::*Method)(TArgs...), T& Instance>
762 static ETL_CONSTEXPR14 TReturn method_instance_stub(
const invocation_element&, TArgs... args)
764 return (Instance.*Method)(etl::forward<TArgs>(args)...);
770 template <
typename T, TReturn (T::*Method)(TArgs...)
const,
const T& Instance>
771 static ETL_CONSTEXPR14 TReturn const_method_instance_stub(
const invocation_element&, TArgs... args)
773 return (Instance.*Method)(etl::forward<TArgs>(args)...);
776#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
780 template <
typename T, T& Instance>
781 static ETL_CONSTEXPR14 TReturn operator_instance_stub(
const invocation_element&, TArgs... args)
783 return Instance.operator()(etl::forward<TArgs>(args)...);
790 template <TReturn (*Method)(TArgs...)>
791 static ETL_CONSTEXPR14 TReturn function_stub(
const invocation_element&, TArgs... args)
793 return (Method)(etl::forward<TArgs>(args)...);
799 static TReturn function_ptr_stub(
const invocation_element& invocation, TArgs... args)
801 return invocation.ptr.fp(etl::forward<TArgs>(args)...);
807 template <
typename TLambda>
808 static ETL_CONSTEXPR14 TReturn lambda_stub(
const invocation_element& invocation, TArgs... arg)
810 ETL_STATIC_ASSERT(is_compatible_callable<TLambda>::value,
"etl::delegate: bound lambda/functor is not compatible with the delegate signature");
812 TLambda* p =
static_cast<TLambda*
>(invocation.ptr.object);
813 return (p->operator())(etl::forward<TArgs>(arg)...);
819 template <
typename TLambda>
820 static ETL_CONSTEXPR14 TReturn const_lambda_stub(
const invocation_element& invocation, TArgs... arg)
822 ETL_STATIC_ASSERT(is_compatible_callable<TLambda>::value,
"etl::delegate: bound lambda/functor is not compatible with the delegate signature");
824 const TLambda* p =
static_cast<const TLambda*
>(invocation.ptr.object);
825 return (p->operator())(etl::forward<TArgs>(arg)...);
831 invocation_element invocation;