Embedded Template Library 1.0
Loading...
Searching...
No Matches
delegate_cpp11.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2019 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31/******************************************************************************
32
33Copyright (C) 2017 by Sergey A Kryukov: derived work
34http://www.SAKryukov.org
35http://www.codeproject.com/Members/SAKryukov
36
37Based on original work by Sergey Ryazanov:
38"The Impossibly Fast C++ Delegates", 18 Jul 2005
39https://www.codeproject.com/articles/11015/the-impossibly-fast-c-delegates
40
41MIT license:
42http://en.wikipedia.org/wiki/MIT_License
43
44Original publication:
45https://www.codeproject.com/Articles/1170503/The-Impossibly-Fast-Cplusplus-Delegates-Fixed
46
47******************************************************************************/
48
49#ifndef ETL_DELEGATE_CPP11_INCLUDED
50#define ETL_DELEGATE_CPP11_INCLUDED
51
52#include "../platform.h"
53#include "../error_handler.h"
54#include "../exception.h"
55#include "../function_traits.h"
56#include "../optional.h"
57#include "../type_list.h"
58#include "../type_traits.h"
59#include "../utility.h"
60
61namespace etl
62{
63 //***************************************************************************
65 //***************************************************************************
66 class delegate_exception : public exception
67 {
68 public:
69
70 delegate_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
71 : exception(reason_, file_name_, line_number_)
72 {
73 }
74 };
75
76 //***************************************************************************
78 //***************************************************************************
80 {
81 public:
82
83 delegate_uninitialised(string_type file_name_, numeric_type line_number_)
84 : delegate_exception(ETL_ERROR_TEXT("delegate:uninitialised", ETL_DELEGATE_FILE_ID"A"), file_name_, line_number_)
85 {
86 }
87 };
88
89 //*****************************************************************
92 //*****************************************************************
93 struct delegate_tag
94 {
95 };
96
97 //***************************************************************************
99 //***************************************************************************
100 template <typename T>
101 struct is_delegate : etl::bool_constant<etl::is_base_of<delegate_tag, T>::value>
102 {
103 };
104
105#if ETL_USING_CPP17
106 template <typename T>
107 inline constexpr bool is_delegate_v = is_delegate<T>::value;
108#endif
109
110 //*************************************************************************
112 //*************************************************************************
113 template <typename T>
114 class delegate;
115
116 //*************************************************************************
118 //*************************************************************************
119 template <typename TReturn, typename... TArgs>
120 class delegate<TReturn(TArgs...)> final : public delegate_tag
121 {
122 private:
123
125 using object_ptr = void*;
126
128 using function_ptr = TReturn (*)(TArgs...);
129
130 public:
131
133 using return_type = TReturn;
134
136 using argument_types = etl::type_list<TArgs...>;
137
138 //*************************************************************************
140 //*************************************************************************
141 ETL_CONSTEXPR14 delegate() ETL_NOEXCEPT
142 {
143 }
144
145 //*************************************************************************
147 //*************************************************************************
148 ETL_CONSTEXPR14 delegate(const delegate& other) = default;
149
150 //*************************************************************************
152 //*************************************************************************
153 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
154 ETL_CONSTEXPR14 delegate(TLambda& instance) ETL_NOEXCEPT
155 {
156 assign(object_ptr(&instance), lambda_stub<TLambda>);
157 }
158
159 //*************************************************************************
161 //*************************************************************************
162 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
163 ETL_CONSTEXPR14 delegate(const TLambda& instance) ETL_NOEXCEPT
164 {
165 assign(object_ptr(&instance), const_lambda_stub<TLambda>);
166 }
167
168 //*************************************************************************
171 //*************************************************************************
172 template <typename TLambda,
173 typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TArgs...)>, TLambda>::value
174 && !etl::is_convertible<TLambda, function_ptr>::value,
175 void>>
176 ETL_CONSTEXPR14 delegate(TLambda&& instance) = delete;
177
178 //*************************************************************************
180 //*************************************************************************
181 explicit ETL_CONSTEXPR14 delegate(function_ptr fp) ETL_NOEXCEPT
182 : invocation(fp, function_ptr_stub)
183 {
184 }
185
186 //*************************************************************************
188 //*************************************************************************
189 template <TReturn (*Method)(TArgs...)>
190 ETL_NODISCARD
191 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
192 {
193 return delegate(function_stub<Method>);
194 }
195
196 //*************************************************************************
198 //*************************************************************************
199 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
200 ETL_NODISCARD
201 static ETL_CONSTEXPR14 delegate create(TLambda& instance) ETL_NOEXCEPT
202 {
203 return delegate(object_ptr(&instance), lambda_stub<TLambda>);
204 }
205
206 //*************************************************************************
208 //*************************************************************************
209 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
210 ETL_NODISCARD
211 static ETL_CONSTEXPR14 delegate create(const TLambda& instance) ETL_NOEXCEPT
212 {
213 return delegate(object_ptr(&instance), const_lambda_stub<TLambda>);
214 }
215
216 //*************************************************************************
218 //*************************************************************************
219 ETL_NODISCARD
220 static ETL_CONSTEXPR14 delegate create(function_ptr fp) ETL_NOEXCEPT
221 {
222 return delegate(fp, function_ptr_stub);
223 }
224
225 //*************************************************************************
227 //*************************************************************************
228 template <typename T, TReturn (T::*Method)(TArgs...)>
229 ETL_NODISCARD
230 static ETL_CONSTEXPR14 delegate create(T& instance) ETL_NOEXCEPT
231 {
232 return delegate(object_ptr(&instance), method_stub<T, Method>);
233 }
234
235 //*************************************************************************
238 //*************************************************************************
239 template <typename T, TReturn (T::*Method)(TArgs...)>
240 ETL_NODISCARD
241 static ETL_CONSTEXPR14 delegate create(T&& instance) = delete;
242
243 //*************************************************************************
245 //*************************************************************************
246 template <typename T, TReturn (T::*Method)(TArgs...) const>
247 ETL_NODISCARD
248 static ETL_CONSTEXPR14 delegate create(const T& instance) ETL_NOEXCEPT
249 {
250 return delegate(object_ptr(&instance), const_method_stub<T, Method>);
251 }
252
253 //*************************************************************************
255 //*************************************************************************
256 template <typename T, TReturn (T::*Method)(TArgs...) const>
257 static ETL_CONSTEXPR14 delegate create(T&& instance) = delete;
258
259 //*************************************************************************
261 //*************************************************************************
262 template <typename T, T& Instance, TReturn (T::*Method)(TArgs...)>
263 ETL_NODISCARD
264 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
265 {
266 return delegate(method_instance_stub<T, Method, Instance>);
267 }
268
269 //*************************************************************************
272 //*************************************************************************
273 template <typename T, TReturn (T::*Method)(TArgs...), T& Instance>
274 ETL_NODISCARD
275 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
276 {
277 return delegate(method_instance_stub<T, Method, Instance>);
278 }
279
280 //*************************************************************************
282 //*************************************************************************
283 template <typename T, T const& Instance, TReturn (T::*Method)(TArgs...) const>
284 ETL_NODISCARD
285 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
286 {
287 return delegate(const_method_instance_stub<T, Method, Instance>);
288 }
289
290 //*************************************************************************
293 //*************************************************************************
294 template <typename T, TReturn (T::*Method)(TArgs...) const, T const& Instance>
295 ETL_NODISCARD
296 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
297 {
298 return delegate(const_method_instance_stub<T, Method, Instance>);
299 }
300
301#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
302 //*************************************************************************
305 //*************************************************************************
306 template <typename T, T& Instance>
307 ETL_NODISCARD
308 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
309 {
310 return delegate(operator_instance_stub<T, Instance>);
311 }
312#endif
313
314 //*************************************************************************
316 //*************************************************************************
317 template <TReturn (*Method)(TArgs...)>
318 ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
319 {
320 assign(function_stub<Method>);
321 }
322
323 //*************************************************************************
325 //*************************************************************************
326 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
327 ETL_CONSTEXPR14 void set(TLambda& instance) ETL_NOEXCEPT
328 {
329 assign(object_ptr(&instance), lambda_stub<TLambda>);
330 }
331
332 //*************************************************************************
334 //*************************************************************************
335 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
336 ETL_CONSTEXPR14 void set(const TLambda& instance) ETL_NOEXCEPT
337 {
338 assign(object_ptr(&instance), const_lambda_stub<TLambda>);
339 }
340
341 //*************************************************************************
343 //*************************************************************************
344 ETL_CONSTEXPR14 void set(function_ptr fp) ETL_NOEXCEPT
345 {
346 assign(fp, function_ptr_stub);
347 }
348
349 //*************************************************************************
351 //*************************************************************************
352 template <typename T, TReturn (T::*Method)(TArgs...)>
353 ETL_CONSTEXPR14 void set(T& instance) ETL_NOEXCEPT
354 {
355 assign(object_ptr(&instance), method_stub<T, Method>);
356 }
357
358 //*************************************************************************
360 //*************************************************************************
361 template <typename T, TReturn (T::*Method)(TArgs...) const>
362 ETL_CONSTEXPR14 void set(T& instance) ETL_NOEXCEPT
363 {
364 assign(object_ptr(&instance), const_method_stub<T, Method>);
365 }
366
367 //*************************************************************************
369 //*************************************************************************
370 template <typename T, T& Instance, TReturn (T::*Method)(TArgs...)>
371 ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
372 {
373 assign(method_instance_stub<T, Method, Instance>);
374 }
375
376 //*************************************************************************
379 //*************************************************************************
380 template <typename T, TReturn (T::*Method)(TArgs...), T& Instance>
381 ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
382 {
383 assign(method_instance_stub<T, Method, Instance>);
384 }
385
386 //*************************************************************************
388 //*************************************************************************
389 template <typename T, T const& Instance, TReturn (T::*Method)(TArgs...) const>
390 ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
391 {
392 assign(const_method_instance_stub<T, Method, Instance>);
393 }
394
395 //*************************************************************************
398 //*************************************************************************
399 template <typename T, TReturn (T::*Method)(TArgs...) const, T const& Instance>
400 ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
401 {
402 assign(const_method_instance_stub<T, Method, Instance>);
403 }
404
405 //*************************************************************************
407 //*************************************************************************
408 ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT
409 {
410 invocation.clear();
411 }
412
413 //*************************************************************************
415 //*************************************************************************
416 template <typename... TCallArgs>
417 ETL_CONSTEXPR14 return_type operator()(TCallArgs&&... args) const
418 {
419 ETL_STATIC_ASSERT((sizeof...(TCallArgs) == sizeof...(TArgs)), "Incorrect number of parameters passed to delegate");
420 ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
421 "Incompatible parameter types passed to delegate");
422
424
425 return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
426 }
427
428 //*************************************************************************
431 //*************************************************************************
432 template <typename TRet = TReturn, typename... TCallArgs>
433 ETL_CONSTEXPR14 typename etl::enable_if_t<etl::is_same<TRet, void>::value, bool> call_if(TCallArgs&&... args) const
434 {
435 ETL_STATIC_ASSERT((sizeof...(TCallArgs) == sizeof...(TArgs)), "Incorrect number of parameters passed to delegate");
436 ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
437 "Incompatible parameter types passed to delegate");
438
439 if (is_valid())
440 {
441 (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
442 return true;
443 }
444 else
445 {
446 return false;
447 }
448 }
449
450 //*************************************************************************
453 //*************************************************************************
454 template <typename TRet = TReturn, typename... TCallArgs>
455 ETL_CONSTEXPR14 typename etl::enable_if_t<!etl::is_same<TRet, void>::value, etl::optional<TReturn>> call_if(TCallArgs&&... args) const
456 {
457 ETL_STATIC_ASSERT((sizeof...(TCallArgs) == sizeof...(TArgs)), "Incorrect number of parameters passed to delegate");
458 ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
459 "Incompatible parameter types passed to delegate");
460
462
463 if (is_valid())
464 {
465 result = (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
466 }
467
468 return result;
469 }
470
471 //*************************************************************************
474 //*************************************************************************
475 template <typename TAlternative, typename... TCallArgs>
476 ETL_CONSTEXPR14 TReturn call_or(TAlternative&& alternative, TCallArgs&&... args) const
477 {
478 ETL_STATIC_ASSERT((sizeof...(TCallArgs) == sizeof...(TArgs)), "Incorrect number of parameters passed to delegate");
479 ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
480 "Incompatible parameter types passed to delegate");
481
482 if (is_valid())
483 {
484 return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
485 }
486 else
487 {
488 return etl::forward<TAlternative>(alternative)(etl::forward<TCallArgs>(args)...);
489 }
490 }
491
492 //*************************************************************************
495 //*************************************************************************
496 template <TReturn (*Method)(TArgs...), typename... TCallArgs>
497 ETL_CONSTEXPR14 TReturn call_or(TCallArgs&&... args) const
498 {
499 ETL_STATIC_ASSERT((sizeof...(TCallArgs) == sizeof...(TArgs)), "Incorrect number of parameters passed to delegate");
500 ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
501 "Incompatible parameter types passed to delegate");
502
503 if (is_valid())
504 {
505 return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
506 }
507 else
508 {
509 return (Method)(etl::forward<TCallArgs>(args)...);
510 }
511 }
512
513 //*************************************************************************
515 //*************************************************************************
516 delegate& operator=(const delegate& rhs) = default;
517
518 //*************************************************************************
520 //*************************************************************************
521 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
522 ETL_CONSTEXPR14 delegate& operator=(TLambda& instance) ETL_NOEXCEPT
523 {
524 assign(object_ptr(&instance), lambda_stub<TLambda>);
525 return *this;
526 }
527
528 //*************************************************************************
530 //*************************************************************************
531 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
532 ETL_CONSTEXPR14 delegate& operator=(const TLambda& instance) ETL_NOEXCEPT
533 {
534 assign(object_ptr(&instance), const_lambda_stub<TLambda>);
535 return *this;
536 }
537
538 //*************************************************************************
540 //*************************************************************************
541 ETL_CONSTEXPR14 delegate& operator=(function_ptr fp) ETL_NOEXCEPT
542 {
543 if (fp == ETL_NULLPTR)
544 {
545 invocation.clear();
546 }
547 else
548 {
549 assign(fp, function_ptr_stub);
550 }
551 return *this;
552 }
553
554 //*************************************************************************
556 //*************************************************************************
557 ETL_NODISCARD ETL_CONSTEXPR14 bool operator==(const delegate& rhs) const ETL_NOEXCEPT
558 {
559 return invocation == rhs.invocation;
560 }
561
562 //*************************************************************************
564 //*************************************************************************
565 ETL_CONSTEXPR14 bool operator!=(const delegate& rhs) const ETL_NOEXCEPT
566 {
567 return invocation != rhs.invocation;
568 }
569
570 //*************************************************************************
572 //*************************************************************************
573 ETL_NODISCARD ETL_CONSTEXPR14 bool is_valid() const ETL_NOEXCEPT
574 {
575 // GCC's UBSan instruments function pointer comparisons, which prevents
576 // constexpr evaluation. Use implicit bool conversion at compile time
577 // to avoid the instrumented != comparison while still checking validity.
578 if (etl::is_constant_evaluated())
579 {
580 return static_cast<bool>(invocation.stub);
581 }
582
583 return invocation.stub != ETL_NULLPTR;
584 }
585
586 //*************************************************************************
588 //*************************************************************************
589 ETL_NODISCARD ETL_CONSTEXPR14 operator bool() const ETL_NOEXCEPT
590 {
591 return is_valid();
592 }
593
594 private:
595
596 //*************************************************************************
597 // Callable compatibility: detects if C (or const C) is invocable with
598 // (TArgs...) and returns a type convertible to TReturn. Works with generic
599 // lambdas and functors.
600 template <typename TCallableType, typename = void>
601 struct is_invocable_with : etl::false_type
602 {
603 };
604
605 template <typename TCallableType>
606 struct is_invocable_with< TCallableType, etl::void_t<decltype(etl::declval<TCallableType&>()(etl::declval<TArgs>()...))>>
607 : etl::bool_constant< etl::is_convertible< decltype(etl::declval<TCallableType&>()(etl::declval<TArgs>()...)), TReturn>::value>
608 {
609 };
610
611 template <typename TCallableType, typename = void>
612 struct is_invocable_with_const : etl::false_type
613 {
614 };
615
616 template <typename TCallableType>
617 struct is_invocable_with_const< TCallableType, etl::void_t<decltype(etl::declval<const TCallableType&>()(etl::declval<TArgs>()...))>>
618 : etl::bool_constant< etl::is_convertible< decltype(etl::declval<const TCallableType&>()(etl::declval<TArgs>()...)), TReturn>::value>
619 {
620 };
621
622 template <typename TCallableType>
623 struct is_compatible_callable : etl::bool_constant<is_invocable_with<TCallableType>::value || is_invocable_with_const<TCallableType>::value>
624 {
625 };
626
627 //*************************************************************************
629 //*************************************************************************
630 struct invocation_element
631 {
633 using stub_type = TReturn (*)(const invocation_element&, TArgs...);
634
635 //***********************************************************************
637 //***********************************************************************
638 ETL_CONSTEXPR14 invocation_element() ETL_NOEXCEPT
639 : ptr(object_ptr(ETL_NULLPTR))
640 , stub(ETL_NULLPTR)
641 {
642 }
643
644 //***********************************************************************
647 //***********************************************************************
648 ETL_CONSTEXPR14 invocation_element(stub_type stub_) ETL_NOEXCEPT
649 : ptr()
650 , stub(stub_)
651 {
652 }
653
654 //***********************************************************************
656 //***********************************************************************
657 ETL_CONSTEXPR14 invocation_element(object_ptr object_, stub_type stub_) ETL_NOEXCEPT
658 : ptr(object_)
659 , stub(stub_)
660 {
661 }
662
663 //***********************************************************************
665 //***********************************************************************
666 ETL_CONSTEXPR14 invocation_element(function_ptr fp_, stub_type stub_) ETL_NOEXCEPT
667 : ptr(fp_)
668 , stub(stub_)
669 {
670 }
671
672 //***********************************************************************
674 //***********************************************************************
675 ETL_CONSTEXPR14 bool operator==(const invocation_element& rhs) const ETL_NOEXCEPT
676 {
677 return (rhs.stub == stub) && ((stub == function_ptr_stub) ? (rhs.ptr.fp == ptr.fp) : (rhs.ptr.object == ptr.object));
678 }
679
680 //***********************************************************************
682 //***********************************************************************
683 ETL_CONSTEXPR14 bool operator!=(const invocation_element& rhs) const ETL_NOEXCEPT
684 {
685 return !operator==(rhs);
686 }
687
688 //***********************************************************************
690 //***********************************************************************
691 ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT
692 {
693 stub = ETL_NULLPTR;
694 }
695
696 //***********************************************************************
698 //***********************************************************************
700 {
702 ETL_CONSTEXPR14 ptr_type() ETL_NOEXCEPT
703 : object(ETL_NULLPTR)
704 {
705 }
706
708 ETL_CONSTEXPR14 ptr_type(object_ptr object_) ETL_NOEXCEPT
709 : object(object_)
710 {
711 }
712
714 ETL_CONSTEXPR14 ptr_type(function_ptr fp_) ETL_NOEXCEPT
715 : fp(fp_)
716 {
717 }
718
719 object_ptr object;
720 function_ptr fp;
721 };
722
723 ptr_type ptr;
724 stub_type stub;
725 };
726
728 using stub_type = typename invocation_element::stub_type;
729
730 //*************************************************************************
732 //*************************************************************************
733 ETL_CONSTEXPR14 delegate(object_ptr object, stub_type stub) ETL_NOEXCEPT
734 : invocation(object, stub)
735 {
736 }
737
738 //*************************************************************************
740 //*************************************************************************
741 ETL_CONSTEXPR14 delegate(function_ptr fp, stub_type stub) ETL_NOEXCEPT
742 : invocation(fp, stub)
743 {
744 }
745
746 //*************************************************************************
748 //*************************************************************************
749 ETL_CONSTEXPR14 delegate(stub_type stub) ETL_NOEXCEPT
750 : invocation(stub)
751 {
752 }
753
754 //*************************************************************************
756 //*************************************************************************
757 ETL_CONSTEXPR14 void assign(object_ptr object, stub_type stub) ETL_NOEXCEPT
758 {
759 invocation.ptr.object = object;
760 invocation.stub = stub;
761 }
762
763 //*************************************************************************
765 //*************************************************************************
766 ETL_CONSTEXPR14 void assign(function_ptr fp, stub_type stub) ETL_NOEXCEPT
767 {
768 invocation.ptr.fp = fp;
769 invocation.stub = stub;
770 }
771
772 //*************************************************************************
774 //*************************************************************************
775 ETL_CONSTEXPR14 void assign(stub_type stub) ETL_NOEXCEPT
776 {
777 invocation.ptr.object = ETL_NULLPTR;
778 invocation.stub = stub;
779 }
780
781 //*************************************************************************
783 //*************************************************************************
784 template <typename T, TReturn (T::*Method)(TArgs...)>
785 static ETL_CONSTEXPR14 TReturn method_stub(const invocation_element& invocation, TArgs... args)
786 {
787 T* p = static_cast<T*>(invocation.ptr.object);
788 return (p->*Method)(etl::forward<TArgs>(args)...);
789 }
790
791 //*************************************************************************
793 //*************************************************************************
794 template <typename T, TReturn (T::*Method)(TArgs...) const>
795 static ETL_CONSTEXPR14 TReturn const_method_stub(const invocation_element& invocation, TArgs... args)
796 {
797 T* const p = static_cast<T*>(invocation.ptr.object);
798 return (p->*Method)(etl::forward<TArgs>(args)...);
799 }
800
801 //*************************************************************************
803 //*************************************************************************
804 template <typename T, TReturn (T::*Method)(TArgs...), T& Instance>
805 static ETL_CONSTEXPR14 TReturn method_instance_stub(const invocation_element&, TArgs... args)
806 {
807 return (Instance.*Method)(etl::forward<TArgs>(args)...);
808 }
809
810 //*************************************************************************
812 //*************************************************************************
813 template <typename T, TReturn (T::*Method)(TArgs...) const, const T& Instance>
814 static ETL_CONSTEXPR14 TReturn const_method_instance_stub(const invocation_element&, TArgs... args)
815 {
816 return (Instance.*Method)(etl::forward<TArgs>(args)...);
817 }
818
819#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
820 //*************************************************************************
822 //*************************************************************************
823 template <typename T, T& Instance>
824 static ETL_CONSTEXPR14 TReturn operator_instance_stub(const invocation_element&, TArgs... args)
825 {
826 return Instance.operator()(etl::forward<TArgs>(args)...);
827 }
828#endif
829
830 //*************************************************************************
832 //*************************************************************************
833 template <TReturn (*Method)(TArgs...)>
834 static ETL_CONSTEXPR14 TReturn function_stub(const invocation_element&, TArgs... args)
835 {
836 return (Method)(etl::forward<TArgs>(args)...);
837 }
838
839 //*************************************************************************
841 //*************************************************************************
842 static TReturn function_ptr_stub(const invocation_element& invocation, TArgs... args)
843 {
844 return invocation.ptr.fp(etl::forward<TArgs>(args)...);
845 }
846
847 //*************************************************************************
849 //*************************************************************************
850 template <typename TLambda>
851 static ETL_CONSTEXPR14 TReturn lambda_stub(const invocation_element& invocation, TArgs... arg)
852 {
853 ETL_STATIC_ASSERT(is_compatible_callable<TLambda>::value, "etl::delegate: bound lambda/functor is not compatible with the delegate signature");
854
855 TLambda* p = static_cast<TLambda*>(invocation.ptr.object);
856 return (p->operator())(etl::forward<TArgs>(arg)...);
857 }
858
859 //*************************************************************************
861 //*************************************************************************
862 template <typename TLambda>
863 static ETL_CONSTEXPR14 TReturn const_lambda_stub(const invocation_element& invocation, TArgs... arg)
864 {
865 ETL_STATIC_ASSERT(is_compatible_callable<TLambda>::value, "etl::delegate: bound lambda/functor is not compatible with the delegate signature");
866
867 const TLambda* p = static_cast<const TLambda*>(invocation.ptr.object);
868 return (p->operator())(etl::forward<TArgs>(arg)...);
869 }
870
871 //*************************************************************************
873 //*************************************************************************
874 invocation_element invocation;
875 };
876
877#if ETL_USING_CPP17
878 //*************************************************************************
880 //*************************************************************************
881 template <auto Function>
882 ETL_NODISCARD
883 constexpr auto make_delegate() ETL_NOEXCEPT
884 {
885 using function_type = typename etl::function_traits<decltype(Function)>::function_type;
886
887 return etl::delegate<function_type>::template create<Function>();
888 }
889
890 //*************************************************************************
892 //*************************************************************************
893 template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value, void>>
894 ETL_NODISCARD
895 constexpr auto make_delegate(TLambda& instance) ETL_NOEXCEPT
896 {
897 using function_type = typename etl::function_traits< decltype(&TLambda::operator())>::function_type;
898
899 return etl::delegate<function_type>(instance);
900 }
901
902 //*************************************************************************
904 //*************************************************************************
905 template <typename T, T& Instance>
906 ETL_NODISCARD
907 constexpr auto make_delegate() ETL_NOEXCEPT
908 {
909 using function_type = typename etl::function_traits<decltype(&T::operator())>::function_type;
910
911 return etl::delegate<function_type>::template create<T, Instance>();
912 }
913
914 //*************************************************************************
916 //*************************************************************************
917 template <typename T, auto Method, T& Instance, typename = etl::enable_if_t< !etl::function_traits<decltype(Method)>::is_const>>
918 ETL_NODISCARD
919 constexpr auto make_delegate() ETL_NOEXCEPT
920 {
921 using function_type = typename etl::function_traits<decltype(Method)>::function_type;
922
923 return etl::delegate<function_type>::template create<T, Method, Instance>();
924 }
925
926 //*************************************************************************
928 //*************************************************************************
929 template <typename T, auto Method, const T& Instance, typename = etl::enable_if_t< etl::function_traits<decltype(Method)>::is_const>>
930 ETL_NODISCARD
931 constexpr auto make_delegate() ETL_NOEXCEPT
932 {
933 using function_type = typename etl::function_traits<decltype(Method)>::function_type;
934
935 return etl::delegate<function_type>::template create<T, Method, Instance>();
936 }
937
938 //*************************************************************************
940 //*************************************************************************
941 template <typename T, auto Method>
942 ETL_NODISCARD
943 constexpr auto make_delegate(T& instance) ETL_NOEXCEPT
944 {
945 using function_type = typename etl::function_traits<decltype(Method)>::function_type;
946
947 return etl::delegate<function_type>::template create<T, Method>(instance);
948 }
949
950 //*************************************************************************
952 //*************************************************************************
953 template <typename T, auto Method>
954 ETL_NODISCARD
955 constexpr auto make_delegate(const T& instance) ETL_NOEXCEPT
956 {
957 using function_type = typename etl::function_traits<decltype(Method)>::function_type;
958
959 return etl::delegate<function_type>::template create<T, Method>(instance);
960 }
961#endif
962} // namespace etl
963
964#endif
ETL_NODISCARD ETL_CONSTEXPR14 bool operator==(const delegate &rhs) const ETL_NOEXCEPT
Checks equality.
Definition delegate_cpp11.h:557
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(const TLambda &instance) ETL_NOEXCEPT
Create from const Lambda or Functor.
Definition delegate_cpp11.h:211
ETL_CONSTEXPR14 delegate(const delegate &other)=default
Copy constructor.
ETL_CONSTEXPR14 bool operator!=(const delegate &rhs) const ETL_NOEXCEPT
Returns true if the delegate is valid.
Definition delegate_cpp11.h:565
ETL_CONSTEXPR14 void set(function_ptr fp) ETL_NOEXCEPT
Set from a function pointer.
Definition delegate_cpp11.h:344
ETL_CONSTEXPR14 void set(TLambda &instance) ETL_NOEXCEPT
Set from Lambda or Functor.
Definition delegate_cpp11.h:327
ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT
Clear the delegate.
Definition delegate_cpp11.h:408
ETL_CONSTEXPR14 delegate(const TLambda &instance) ETL_NOEXCEPT
Construct from a const lambda or functor.
Definition delegate_cpp11.h:163
ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
Set from function (Compile time).
Definition delegate_cpp11.h:318
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
Definition delegate_cpp11.h:308
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(T &instance) ETL_NOEXCEPT
Create from instance method (Run time).
Definition delegate_cpp11.h:230
ETL_CONSTEXPR14 delegate(function_ptr fp) ETL_NOEXCEPT
Construct from a function pointer.
Definition delegate_cpp11.h:181
ETL_CONSTEXPR14 TReturn call_or(TCallArgs &&... args) const
Definition delegate_cpp11.h:497
ETL_CONSTEXPR14 delegate & operator=(function_ptr fp) ETL_NOEXCEPT
Assign from a function pointer.
Definition delegate_cpp11.h:541
delegate & operator=(const delegate &rhs)=default
Assignment.
ETL_CONSTEXPR14 delegate(TLambda &&instance)=delete
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
Create from function (Compile time).
Definition delegate_cpp11.h:191
static ETL_CONSTEXPR14 delegate create(T &&instance)=delete
Disable create from rvalue instance method (Run time).
etl::type_list< TArgs... > argument_types
Type list of the delegate's argument types.
Definition delegate_cpp11.h:136
ETL_CONSTEXPR14 etl::enable_if_t< etl::is_same< TRet, void >::value, bool > call_if(TCallArgs &&... args) const
Definition delegate_cpp11.h:433
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(T &&instance)=delete
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(TLambda &instance) ETL_NOEXCEPT
Create from Lambda or Functor.
Definition delegate_cpp11.h:201
ETL_CONSTEXPR14 return_type operator()(TCallArgs &&... args) const
Execute the delegate.
Definition delegate_cpp11.h:417
ETL_CONSTEXPR14 TReturn call_or(TAlternative &&alternative, TCallArgs &&... args) const
Definition delegate_cpp11.h:476
ETL_CONSTEXPR14 delegate & operator=(TLambda &instance) ETL_NOEXCEPT
Create from Lambda or Functor.
Definition delegate_cpp11.h:522
ETL_CONSTEXPR14 delegate() ETL_NOEXCEPT
Default constructor.
Definition delegate_cpp11.h:141
TReturn return_type
The delegate's return type.
Definition delegate_cpp11.h:133
ETL_CONSTEXPR14 delegate(TLambda &instance) ETL_NOEXCEPT
Construct from a lambda or functor.
Definition delegate_cpp11.h:154
ETL_CONSTEXPR14 delegate & operator=(const TLambda &instance) ETL_NOEXCEPT
Create from const Lambda or Functor.
Definition delegate_cpp11.h:532
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
Create from instance method (Compile time).
Definition delegate_cpp11.h:264
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(const T &instance) ETL_NOEXCEPT
Create from const instance method (Run time).
Definition delegate_cpp11.h:248
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(function_ptr fp) ETL_NOEXCEPT
Create from a function pointer.
Definition delegate_cpp11.h:220
ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
Set from instance method (Compile time).
Definition delegate_cpp11.h:371
ETL_CONSTEXPR14 void set(T &instance) ETL_NOEXCEPT
Set from instance method (Run time).
Definition delegate_cpp11.h:353
ETL_CONSTEXPR14 void set(const TLambda &instance) ETL_NOEXCEPT
Set from const Lambda or Functor.
Definition delegate_cpp11.h:336
ETL_CONSTEXPR14 etl::enable_if_t<!etl::is_same< TRet, void >::value, etl::optional< TReturn > > call_if(TCallArgs &&... args) const
Definition delegate_cpp11.h:455
ETL_NODISCARD ETL_CONSTEXPR14 bool is_valid() const ETL_NOEXCEPT
Returns true if the delegate is valid.
Definition delegate_cpp11.h:573
The base class for delegate exceptions.
Definition delegate_cpp03.h:149
The exception thrown when the delegate is uninitialised.
Definition delegate_cpp03.h:162
Declaration.
Definition delegate_cpp03.h:191
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition exception.h:59
Definition optional.h:1238
Definition absolute.h:40
integral_constant< bool, false > false_type
integral_constant specialisations
Definition type_traits.h:80
Definition type_traits.h:97
Definition delegate_cpp03.h:176
is_delegate
Definition delegate_cpp03.h:184
ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Equality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:903
ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Inequality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:937
ETL_CONSTEXPR14 ptr_type(object_ptr object_) ETL_NOEXCEPT
Constructs with the object pointer as the active member.
Definition delegate_cpp11.h:708
ETL_CONSTEXPR14 ptr_type(function_ptr fp_) ETL_NOEXCEPT
Constructs with the function pointer as the active member.
Definition delegate_cpp11.h:714
ETL_CONSTEXPR14 ptr_type() ETL_NOEXCEPT
Default-constructs with a null object pointer as the active member.
Definition delegate_cpp11.h:702