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
124 using object_ptr = void*;
125 using function_ptr = TReturn (*)(TArgs...);
126
127 public:
128
129 using return_type = TReturn;
130 using argument_types = etl::type_list<TArgs...>;
131
132 //*************************************************************************
134 //*************************************************************************
135 ETL_CONSTEXPR14 delegate() ETL_NOEXCEPT
136 {
137 }
138
139 //*************************************************************************
140 // Copy constructor.
141 //*************************************************************************
142 ETL_CONSTEXPR14 delegate(const delegate& other) = default;
143
144 //*************************************************************************
145 // Construct from lambda or functor.
146 //*************************************************************************
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
149 {
150 assign(object_ptr(&instance), lambda_stub<TLambda>);
151 }
152
153 //*************************************************************************
154 // Construct from const lambda or functor.
155 //*************************************************************************
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
158 {
159 assign(object_ptr(&instance), const_lambda_stub<TLambda>);
160 }
161
162 //*************************************************************************
163 // Delete construction from rvalue reference lambda or functor.
164 // Excludes non-capturing lambdas convertible to a function pointer.
165 //*************************************************************************
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,
169 void>>
170 ETL_CONSTEXPR14 delegate(TLambda&& instance) = delete;
171
172 //*************************************************************************
173 // Construct from a function pointer.
174 //*************************************************************************
175 delegate(function_ptr fp) ETL_NOEXCEPT
176 {
177 assign(fp, function_ptr_stub);
178 }
179
180 //*************************************************************************
182 //*************************************************************************
183 template <TReturn (*Method)(TArgs...)>
184 ETL_NODISCARD
185 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
186 {
187 return delegate(function_stub<Method>);
188 }
189
190 //*************************************************************************
192 //*************************************************************************
193 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
194 ETL_NODISCARD
195 static ETL_CONSTEXPR14 delegate create(TLambda& instance) ETL_NOEXCEPT
196 {
197 return delegate(object_ptr(&instance), lambda_stub<TLambda>);
198 }
199
200 //*************************************************************************
202 //*************************************************************************
203 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
204 ETL_NODISCARD
205 static ETL_CONSTEXPR14 delegate create(const TLambda& instance) ETL_NOEXCEPT
206 {
207 return delegate(object_ptr(&instance), const_lambda_stub<TLambda>);
208 }
209
210 //*************************************************************************
211 // Create from a function pointer.
212 //*************************************************************************
213 ETL_NODISCARD
214 static delegate create(function_ptr fp) ETL_NOEXCEPT
215 {
216 return delegate(fp, function_ptr_stub);
217 }
218
219 //*************************************************************************
221 //*************************************************************************
222 template <typename T, TReturn (T::*Method)(TArgs...)>
223 ETL_NODISCARD
224 static ETL_CONSTEXPR14 delegate create(T& instance) ETL_NOEXCEPT
225 {
226 return delegate(object_ptr(&instance), method_stub<T, Method>);
227 }
228
229 //*************************************************************************
232 //*************************************************************************
233 template <typename T, TReturn (T::*Method)(TArgs...)>
234 ETL_NODISCARD
235 static ETL_CONSTEXPR14 delegate create(T&& instance) = delete;
236
237 //*************************************************************************
239 //*************************************************************************
240 template <typename T, TReturn (T::*Method)(TArgs...) const>
241 ETL_NODISCARD
242 static ETL_CONSTEXPR14 delegate create(const T& instance) ETL_NOEXCEPT
243 {
244 return delegate(object_ptr(&instance), const_method_stub<T, Method>);
245 }
246
247 //*************************************************************************
249 //*************************************************************************
250 template <typename T, TReturn (T::*Method)(TArgs...) const>
251 static ETL_CONSTEXPR14 delegate create(T&& instance) = delete;
252
253 //*************************************************************************
255 //*************************************************************************
256 template <typename T, T& Instance, TReturn (T::*Method)(TArgs...)>
257 ETL_NODISCARD
258 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
259 {
260 return delegate(method_instance_stub<T, Method, Instance>);
261 }
262
263 //*************************************************************************
266 //*************************************************************************
267 template <typename T, TReturn (T::*Method)(TArgs...), T& Instance>
268 ETL_NODISCARD
269 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
270 {
271 return delegate(method_instance_stub<T, Method, Instance>);
272 }
273
274 //*************************************************************************
276 //*************************************************************************
277 template <typename T, T const& Instance, TReturn (T::*Method)(TArgs...) const>
278 ETL_NODISCARD
279 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
280 {
281 return delegate(const_method_instance_stub<T, Method, Instance>);
282 }
283
284 //*************************************************************************
287 //*************************************************************************
288 template <typename T, TReturn (T::*Method)(TArgs...) const, T const& Instance>
289 ETL_NODISCARD
290 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
291 {
292 return delegate(const_method_instance_stub<T, Method, Instance>);
293 }
294
295#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
296 //*************************************************************************
299 //*************************************************************************
300 template <typename T, T& Instance>
301 ETL_NODISCARD
302 static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
303 {
304 return delegate(operator_instance_stub<T, Instance>);
305 }
306#endif
307
308 //*************************************************************************
310 //*************************************************************************
311 template <TReturn (*Method)(TArgs...)>
312 ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
313 {
314 assign(function_stub<Method>);
315 }
316
317 //*************************************************************************
319 //*************************************************************************
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
322 {
323 assign(object_ptr(&instance), lambda_stub<TLambda>);
324 }
325
326 //*************************************************************************
328 //*************************************************************************
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
331 {
332 assign(object_ptr(&instance), const_lambda_stub<TLambda>);
333 }
334
335 //*************************************************************************
336 // Set from a function pointer.
337 //*************************************************************************
338 void set(function_ptr fp) ETL_NOEXCEPT
339 {
340 assign(fp, function_ptr_stub);
341 }
342
343 //*************************************************************************
345 //*************************************************************************
346 template <typename T, TReturn (T::*Method)(TArgs...)>
347 ETL_CONSTEXPR14 void set(T& instance) ETL_NOEXCEPT
348 {
349 assign(object_ptr(&instance), method_stub<T, Method>);
350 }
351
352 //*************************************************************************
354 //*************************************************************************
355 template <typename T, TReturn (T::*Method)(TArgs...) const>
356 ETL_CONSTEXPR14 void set(T& instance) ETL_NOEXCEPT
357 {
358 assign(object_ptr(&instance), const_method_stub<T, Method>);
359 }
360
361 //*************************************************************************
363 //*************************************************************************
364 template <typename T, T& Instance, TReturn (T::*Method)(TArgs...)>
365 ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
366 {
367 assign(method_instance_stub<T, Method, Instance>);
368 }
369
370 //*************************************************************************
373 //*************************************************************************
374 template <typename T, TReturn (T::*Method)(TArgs...), T& Instance>
375 ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
376 {
377 assign(method_instance_stub<T, Method, Instance>);
378 }
379
380 //*************************************************************************
382 //*************************************************************************
383 template <typename T, T const& Instance, TReturn (T::*Method)(TArgs...) const>
384 ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
385 {
386 assign(const_method_instance_stub<T, Method, Instance>);
387 }
388
389 //*************************************************************************
392 //*************************************************************************
393 template <typename T, TReturn (T::*Method)(TArgs...) const, T const& Instance>
394 ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
395 {
396 assign(const_method_instance_stub<T, Method, Instance>);
397 }
398
399 //*************************************************************************
401 //*************************************************************************
402 ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT
403 {
404 invocation.clear();
405 }
406
407 //*************************************************************************
409 //*************************************************************************
410 template <typename... TCallArgs>
411 ETL_CONSTEXPR14 return_type operator()(TCallArgs&&... args) const
412 {
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");
416
418
419 return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
420 }
421
422 //*************************************************************************
425 //*************************************************************************
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
428 {
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");
432
433 if (is_valid())
434 {
435 (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
436 return true;
437 }
438 else
439 {
440 return false;
441 }
442 }
443
444 //*************************************************************************
447 //*************************************************************************
448 template <typename TRet = TReturn, typename... TCallArgs>
449 ETL_CONSTEXPR14 typename etl::enable_if_t<!etl::is_same<TRet, void>::value, etl::optional<TReturn>> call_if(TCallArgs&&... args) const
450 {
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");
454
456
457 if (is_valid())
458 {
459 result = (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
460 }
461
462 return result;
463 }
464
465 //*************************************************************************
468 //*************************************************************************
469 template <typename TAlternative, typename... TCallArgs>
470 ETL_CONSTEXPR14 TReturn call_or(TAlternative&& alternative, TCallArgs&&... args) const
471 {
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");
475
476 if (is_valid())
477 {
478 return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
479 }
480 else
481 {
482 return etl::forward<TAlternative>(alternative)(etl::forward<TCallArgs>(args)...);
483 }
484 }
485
486 //*************************************************************************
489 //*************************************************************************
490 template <TReturn (*Method)(TArgs...), typename... TCallArgs>
491 ETL_CONSTEXPR14 TReturn call_or(TCallArgs&&... args) const
492 {
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");
496
497 if (is_valid())
498 {
499 return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
500 }
501 else
502 {
503 return (Method)(etl::forward<TCallArgs>(args)...);
504 }
505 }
506
507 //*************************************************************************
509 //*************************************************************************
510 delegate& operator=(const delegate& rhs) = default;
511
512 //*************************************************************************
514 //*************************************************************************
515 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
516 ETL_CONSTEXPR14 delegate& operator=(TLambda& instance) ETL_NOEXCEPT
517 {
518 assign(object_ptr(&instance), lambda_stub<TLambda>);
519 return *this;
520 }
521
522 //*************************************************************************
524 //*************************************************************************
525 template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
526 ETL_CONSTEXPR14 delegate& operator=(const TLambda& instance) ETL_NOEXCEPT
527 {
528 assign(object_ptr(&instance), const_lambda_stub<TLambda>);
529 return *this;
530 }
531
532 //*************************************************************************
533 // Create from a function pointer.
534 //*************************************************************************
535 delegate& operator=(function_ptr fp) ETL_NOEXCEPT
536 {
537 assign(fp, function_ptr_stub);
538 return *this;
539 }
540
541 //*************************************************************************
543 //*************************************************************************
544 ETL_NODISCARD ETL_CONSTEXPR14 bool operator==(const delegate& rhs) const ETL_NOEXCEPT
545 {
546 return invocation == rhs.invocation;
547 }
548
549 //*************************************************************************
551 //*************************************************************************
552 ETL_CONSTEXPR14 bool operator!=(const delegate& rhs) const ETL_NOEXCEPT
553 {
554 return invocation != rhs.invocation;
555 }
556
557 //*************************************************************************
559 //*************************************************************************
560 ETL_NODISCARD ETL_CONSTEXPR14 bool is_valid() const ETL_NOEXCEPT
561 {
562 return invocation.stub != ETL_NULLPTR;
563 }
564
565 //*************************************************************************
567 //*************************************************************************
568 ETL_NODISCARD ETL_CONSTEXPR14 operator bool() const ETL_NOEXCEPT
569 {
570 return is_valid();
571 }
572
573 private:
574
575 //*************************************************************************
576 // Callable compatibility: detects if C (or const C) is invocable with
577 // (TArgs...) and returns a type convertible to TReturn. Works with generic
578 // lambdas and functors.
579 template <typename TCallableType, typename = void>
580 struct is_invocable_with : etl::false_type
581 {
582 };
583
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>
587 {
588 };
589
590 template <typename TCallableType, typename = void>
591 struct is_invocable_with_const : etl::false_type
592 {
593 };
594
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>
598 {
599 };
600
601 template <typename TCallableType>
602 struct is_compatible_callable : etl::bool_constant<is_invocable_with<TCallableType>::value || is_invocable_with_const<TCallableType>::value>
603 {
604 };
605
606 //*************************************************************************
608 //*************************************************************************
609 struct invocation_element
610 {
611 using stub_type = TReturn (*)(const invocation_element&, TArgs...);
612
613 //***********************************************************************
614 ETL_CONSTEXPR14 invocation_element() ETL_NOEXCEPT
615 : ptr(object_ptr(ETL_NULLPTR))
616 , stub(ETL_NULLPTR)
617 {
618 }
619
620 //***********************************************************************
621 ETL_CONSTEXPR14 invocation_element(stub_type stub_) ETL_NOEXCEPT
622 : ptr()
623 , stub(stub_)
624 {
625 }
626
627 //***********************************************************************
628 ETL_CONSTEXPR14 invocation_element(object_ptr object_, stub_type stub_) ETL_NOEXCEPT
629 : ptr(object_)
630 , stub(stub_)
631 {
632 }
633
634 //***********************************************************************
635 ETL_CONSTEXPR14 invocation_element(function_ptr fp_, stub_type stub_) ETL_NOEXCEPT
636 : ptr(fp_)
637 , stub(stub_)
638 {
639 }
640
641 //***********************************************************************
642 ETL_CONSTEXPR14 bool operator==(const invocation_element& rhs) const ETL_NOEXCEPT
643 {
644 return (rhs.stub == stub) && ((stub == function_ptr_stub) ? (rhs.ptr.fp == ptr.fp) : (rhs.ptr.object == ptr.object));
645 }
646
647 //***********************************************************************
648 ETL_CONSTEXPR14 bool operator!=(const invocation_element& rhs) const ETL_NOEXCEPT
649 {
650 return !operator==(rhs);
651 }
652
653 //***********************************************************************
654 ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT
655 {
656 stub = ETL_NULLPTR;
657 }
658
659 //***********************************************************************
660 union ptr_type
661 {
662 ETL_CONSTEXPR14 ptr_type() ETL_NOEXCEPT
663 : object(ETL_NULLPTR)
664 {
665 }
666
667 ETL_CONSTEXPR14 ptr_type(object_ptr object_) ETL_NOEXCEPT
668 : object(object_)
669 {
670 }
671
672 ETL_CONSTEXPR14 ptr_type(function_ptr fp_) ETL_NOEXCEPT
673 : fp(fp_)
674 {
675 }
676
677 object_ptr object;
678 function_ptr fp;
679 };
680
681 ptr_type ptr;
682 stub_type stub;
683 };
684
685 using stub_type = typename invocation_element::stub_type;
686
687 //*************************************************************************
689 //*************************************************************************
690 ETL_CONSTEXPR14 delegate(object_ptr object, stub_type stub) ETL_NOEXCEPT
691 : invocation(object, stub)
692 {
693 }
694
695 //*************************************************************************
697 //*************************************************************************
698 ETL_CONSTEXPR14 delegate(function_ptr fp, stub_type stub) ETL_NOEXCEPT
699 : invocation(fp, stub)
700 {
701 }
702
703 //*************************************************************************
705 //*************************************************************************
706 ETL_CONSTEXPR14 delegate(stub_type stub) ETL_NOEXCEPT
707 : invocation(stub)
708 {
709 }
710
711 //*************************************************************************
713 //*************************************************************************
714 ETL_CONSTEXPR14 void assign(object_ptr object, stub_type stub) ETL_NOEXCEPT
715 {
716 invocation.ptr.object = object;
717 invocation.stub = stub;
718 }
719
720 //*************************************************************************
722 //*************************************************************************
723 ETL_CONSTEXPR14 void assign(function_ptr fp, stub_type stub) ETL_NOEXCEPT
724 {
725 invocation.ptr.fp = fp;
726 invocation.stub = stub;
727 }
728
729 //*************************************************************************
731 //*************************************************************************
732 ETL_CONSTEXPR14 void assign(stub_type stub) ETL_NOEXCEPT
733 {
734 invocation.ptr.object = ETL_NULLPTR;
735 invocation.stub = stub;
736 }
737
738 //*************************************************************************
740 //*************************************************************************
741 template <typename T, TReturn (T::*Method)(TArgs...)>
742 static ETL_CONSTEXPR14 TReturn method_stub(const invocation_element& invocation, TArgs... args)
743 {
744 T* p = static_cast<T*>(invocation.ptr.object);
745 return (p->*Method)(etl::forward<TArgs>(args)...);
746 }
747
748 //*************************************************************************
750 //*************************************************************************
751 template <typename T, TReturn (T::*Method)(TArgs...) const>
752 static ETL_CONSTEXPR14 TReturn const_method_stub(const invocation_element& invocation, TArgs... args)
753 {
754 T* const p = static_cast<T*>(invocation.ptr.object);
755 return (p->*Method)(etl::forward<TArgs>(args)...);
756 }
757
758 //*************************************************************************
760 //*************************************************************************
761 template <typename T, TReturn (T::*Method)(TArgs...), T& Instance>
762 static ETL_CONSTEXPR14 TReturn method_instance_stub(const invocation_element&, TArgs... args)
763 {
764 return (Instance.*Method)(etl::forward<TArgs>(args)...);
765 }
766
767 //*************************************************************************
769 //*************************************************************************
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)
772 {
773 return (Instance.*Method)(etl::forward<TArgs>(args)...);
774 }
775
776#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
777 //*************************************************************************
779 //*************************************************************************
780 template <typename T, T& Instance>
781 static ETL_CONSTEXPR14 TReturn operator_instance_stub(const invocation_element&, TArgs... args)
782 {
783 return Instance.operator()(etl::forward<TArgs>(args)...);
784 }
785#endif
786
787 //*************************************************************************
789 //*************************************************************************
790 template <TReturn (*Method)(TArgs...)>
791 static ETL_CONSTEXPR14 TReturn function_stub(const invocation_element&, TArgs... args)
792 {
793 return (Method)(etl::forward<TArgs>(args)...);
794 }
795
796 //*************************************************************************
798 //*************************************************************************
799 static TReturn function_ptr_stub(const invocation_element& invocation, TArgs... args)
800 {
801 return invocation.ptr.fp(etl::forward<TArgs>(args)...);
802 }
803
804 //*************************************************************************
806 //*************************************************************************
807 template <typename TLambda>
808 static ETL_CONSTEXPR14 TReturn lambda_stub(const invocation_element& invocation, TArgs... arg)
809 {
810 ETL_STATIC_ASSERT(is_compatible_callable<TLambda>::value, "etl::delegate: bound lambda/functor is not compatible with the delegate signature");
811
812 TLambda* p = static_cast<TLambda*>(invocation.ptr.object);
813 return (p->operator())(etl::forward<TArgs>(arg)...);
814 }
815
816 //*************************************************************************
818 //*************************************************************************
819 template <typename TLambda>
820 static ETL_CONSTEXPR14 TReturn const_lambda_stub(const invocation_element& invocation, TArgs... arg)
821 {
822 ETL_STATIC_ASSERT(is_compatible_callable<TLambda>::value, "etl::delegate: bound lambda/functor is not compatible with the delegate signature");
823
824 const TLambda* p = static_cast<const TLambda*>(invocation.ptr.object);
825 return (p->operator())(etl::forward<TArgs>(arg)...);
826 }
827
828 //*************************************************************************
830 //*************************************************************************
831 invocation_element invocation;
832 };
833
834#if ETL_USING_CPP17
835 //*************************************************************************
837 //*************************************************************************
838 template <auto Function>
839 ETL_NODISCARD
840 constexpr auto make_delegate() ETL_NOEXCEPT
841 {
842 using function_type = typename etl::function_traits<decltype(Function)>::function_type;
843
844 return etl::delegate<function_type>::template create<Function>();
845 }
846
847 //*************************************************************************
849 //*************************************************************************
850 template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value, void>>
851 ETL_NODISCARD
852 constexpr auto make_delegate(TLambda& instance) ETL_NOEXCEPT
853 {
854 using function_type = typename etl::function_traits< decltype(&TLambda::operator())>::function_type;
855
856 return etl::delegate<function_type>(instance);
857 }
858
859 //*************************************************************************
861 //*************************************************************************
862 template <typename T, T& Instance>
863 ETL_NODISCARD
864 constexpr auto make_delegate() ETL_NOEXCEPT
865 {
866 using function_type = typename etl::function_traits<decltype(&T::operator())>::function_type;
867
868 return etl::delegate<function_type>::template create<T, Instance>();
869 }
870
871 //*************************************************************************
873 //*************************************************************************
874 template <typename T, auto Method, T& Instance, typename = etl::enable_if_t< !etl::function_traits<decltype(Method)>::is_const>>
875 ETL_NODISCARD
876 constexpr auto make_delegate() ETL_NOEXCEPT
877 {
878 using function_type = typename etl::function_traits<decltype(Method)>::function_type;
879
880 return etl::delegate<function_type>::template create<T, Method, Instance>();
881 }
882
883 //*************************************************************************
885 //*************************************************************************
886 template <typename T, auto Method, const T& Instance, typename = etl::enable_if_t< etl::function_traits<decltype(Method)>::is_const>>
887 ETL_NODISCARD
888 constexpr auto make_delegate() ETL_NOEXCEPT
889 {
890 using function_type = typename etl::function_traits<decltype(Method)>::function_type;
891
892 return etl::delegate<function_type>::template create<T, Method, Instance>();
893 }
894
895 //*************************************************************************
897 //*************************************************************************
898 template <typename T, auto Method>
899 ETL_NODISCARD
900 constexpr auto make_delegate(T& instance) ETL_NOEXCEPT
901 {
902 using function_type = typename etl::function_traits<decltype(Method)>::function_type;
903
904 return etl::delegate<function_type>::template create<T, Method>(instance);
905 }
906
907 //*************************************************************************
909 //*************************************************************************
910 template <typename T, auto Method>
911 ETL_NODISCARD
912 constexpr auto make_delegate(const T& instance) ETL_NOEXCEPT
913 {
914 using function_type = typename etl::function_traits<decltype(Method)>::function_type;
915
916 return etl::delegate<function_type>::template create<T, Method>(instance);
917 }
918#endif
919} // namespace etl
920
921#endif
ETL_NODISCARD ETL_CONSTEXPR14 bool operator==(const delegate &rhs) const ETL_NOEXCEPT
Checks equality.
Definition delegate_cpp11.h:544
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(const TLambda &instance) ETL_NOEXCEPT
Create from const Lambda or Functor.
Definition delegate_cpp11.h:205
ETL_CONSTEXPR14 bool operator!=(const delegate &rhs) const ETL_NOEXCEPT
Returns true if the delegate is valid.
Definition delegate_cpp11.h:552
ETL_CONSTEXPR14 void set(TLambda &instance) ETL_NOEXCEPT
Set from Lambda or Functor.
Definition delegate_cpp11.h:321
ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT
Clear the delegate.
Definition delegate_cpp11.h:402
ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
Set from function (Compile time).
Definition delegate_cpp11.h:312
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
Definition delegate_cpp11.h:302
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(T &instance) ETL_NOEXCEPT
Create from instance method (Run time).
Definition delegate_cpp11.h:224
ETL_CONSTEXPR14 TReturn call_or(TCallArgs &&... args) const
Definition delegate_cpp11.h:491
delegate & operator=(const delegate &rhs)=default
Assignment.
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
Create from function (Compile time).
Definition delegate_cpp11.h:185
static ETL_CONSTEXPR14 delegate create(T &&instance)=delete
Disable create from rvalue instance method (Run time).
ETL_CONSTEXPR14 etl::enable_if_t< etl::is_same< TRet, void >::value, bool > call_if(TCallArgs &&... args) const
Definition delegate_cpp11.h:427
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:195
ETL_CONSTEXPR14 return_type operator()(TCallArgs &&... args) const
Execute the delegate.
Definition delegate_cpp11.h:411
ETL_CONSTEXPR14 TReturn call_or(TAlternative &&alternative, TCallArgs &&... args) const
Definition delegate_cpp11.h:470
ETL_CONSTEXPR14 delegate & operator=(TLambda &instance) ETL_NOEXCEPT
Create from Lambda or Functor.
Definition delegate_cpp11.h:516
ETL_CONSTEXPR14 delegate() ETL_NOEXCEPT
Default constructor.
Definition delegate_cpp11.h:135
ETL_CONSTEXPR14 delegate & operator=(const TLambda &instance) ETL_NOEXCEPT
Create from const Lambda or Functor.
Definition delegate_cpp11.h:526
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
Create from instance method (Compile time).
Definition delegate_cpp11.h:258
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(const T &instance) ETL_NOEXCEPT
Create from const instance method (Run time).
Definition delegate_cpp11.h:242
ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
Set from instance method (Compile time).
Definition delegate_cpp11.h:365
ETL_CONSTEXPR14 void set(T &instance) ETL_NOEXCEPT
Set from instance method (Run time).
Definition delegate_cpp11.h:347
ETL_CONSTEXPR14 void set(const TLambda &instance) ETL_NOEXCEPT
Set from const Lambda or Functor.
Definition delegate_cpp11.h:330
ETL_CONSTEXPR14 etl::enable_if_t<!etl::is_same< TRet, void >::value, etl::optional< TReturn > > call_if(TCallArgs &&... args) const
Definition delegate_cpp11.h:449
ETL_NODISCARD ETL_CONSTEXPR14 bool is_valid() const ETL_NOEXCEPT
Returns true if the delegate is valid.
Definition delegate_cpp11.h:560
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
Definition optional.h:1273
A templated set implementation that uses a fixed size buffer.
Definition set.h:2550
ETL_CONSTEXPR14 bool operator!=(const etl::bitset< Active_Bits, TElement > &lhs, const etl::bitset< Active_Bits, TElement > &rhs) ETL_NOEXCEPT
Definition bitset_new.h:2529
#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
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1081
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