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: https://www.codeproject.com/Articles/1170503/The-Impossibly-Fast-Cplusplus-Delegates-Fixed
45
46******************************************************************************/
47
48#ifndef ETL_DELEGATE_CPP11_INCLUDED
49#define ETL_DELEGATE_CPP11_INCLUDED
50
51#include "../platform.h"
52#include "../error_handler.h"
53#include "../exception.h"
54#include "../type_traits.h"
55#include "../utility.h"
56#include "../optional.h"
57
58namespace etl
59{
60 //***************************************************************************
62 //***************************************************************************
63 class delegate_exception : public exception
64 {
65 public:
66
67 delegate_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
68 : exception(reason_, file_name_, line_number_)
69 {
70 }
71 };
72
73 //***************************************************************************
75 //***************************************************************************
76 class delegate_uninitialised : public delegate_exception
77 {
78 public:
79
80 delegate_uninitialised(string_type file_name_, numeric_type line_number_)
81 : delegate_exception(ETL_ERROR_TEXT("delegate:uninitialised", ETL_DELEGATE_FILE_ID"A"), file_name_, line_number_)
82 {
83 }
84 };
85
86 //*************************************************************************
88 //*************************************************************************
89 template <typename T> class delegate;
90
91 //*************************************************************************
93 //*************************************************************************
94 template <typename TReturn, typename... TParams>
95 class delegate<TReturn(TParams...)> final
96 {
97 public:
98
99 //*************************************************************************
101 //*************************************************************************
102 ETL_CONSTEXPR14 delegate()
103 {
104 }
105
106 //*************************************************************************
107 // Copy constructor.
108 //*************************************************************************
109 ETL_CONSTEXPR14 delegate(const delegate& other) = default;
110
111 //*************************************************************************
112 // Construct from lambda or functor.
113 //*************************************************************************
115 ETL_CONSTEXPR14 delegate(TLambda& instance)
116 {
117 assign((void*)(&instance), lambda_stub<TLambda>);
118 }
119
120 //*************************************************************************
121 // Construct from const lambda or functor.
122 //*************************************************************************
123 template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
124 ETL_CONSTEXPR14 delegate(const TLambda& instance)
125 {
126 assign((void*)(&instance), const_lambda_stub<TLambda>);
127 }
128
129 //*************************************************************************
131 //*************************************************************************
132 template <TReturn(*Method)(TParams...)>
133 ETL_NODISCARD
134 static ETL_CONSTEXPR14 delegate create()
135 {
136 return delegate(ETL_NULLPTR, function_stub<Method>);
137 }
138
139 //*************************************************************************
141 //*************************************************************************
143 ETL_NODISCARD
144 static ETL_CONSTEXPR14 delegate create(TLambda& instance)
145 {
146 return delegate((void*)(&instance), lambda_stub<TLambda>);
147 }
148
149 //*************************************************************************
151 //*************************************************************************
153 ETL_NODISCARD
154 static ETL_CONSTEXPR14 delegate create(const TLambda& instance)
155 {
156 return delegate((void*)(&instance), const_lambda_stub<TLambda>);
157 }
158
159 //*************************************************************************
161 //*************************************************************************
162 template <typename T, TReturn(T::*Method)(TParams...)>
163 ETL_NODISCARD
164 static ETL_CONSTEXPR14 delegate create(T& instance)
165 {
166 return delegate((void*)(&instance), method_stub<T, Method>);
167 }
168
169 //*************************************************************************
172 //*************************************************************************
173 template <typename T, TReturn(T::*Method)(TParams...)>
174 ETL_NODISCARD
175 static ETL_CONSTEXPR14 delegate create(T&& instance) = delete;
176
177 //*************************************************************************
179 //*************************************************************************
180 template <typename T, TReturn(T::*Method)(TParams...) const>
181 ETL_NODISCARD
182 static ETL_CONSTEXPR14 delegate create(const T& instance)
183 {
184 return delegate((void*)(&instance), const_method_stub<T, Method>);
185 }
186
187 //*************************************************************************
189 //*************************************************************************
190 template <typename T, TReturn(T::*Method)(TParams...) const>
191 static ETL_CONSTEXPR14 delegate create(T&& instance) = delete;
192
193 //*************************************************************************
195 //*************************************************************************
196 template <typename T, T& Instance, TReturn(T::*Method)(TParams...)>
197 ETL_NODISCARD
198 static ETL_CONSTEXPR14 delegate create()
199 {
201 }
202
203 //*************************************************************************
206 //*************************************************************************
207 template <typename T, TReturn(T::* Method)(TParams...), T& Instance>
208 ETL_NODISCARD
209 static ETL_CONSTEXPR14 delegate create()
210 {
212 }
213
214 //*************************************************************************
216 //*************************************************************************
217 template <typename T, T const& Instance, TReturn(T::*Method)(TParams...) const>
218 ETL_NODISCARD
223
224 //*************************************************************************
227 //*************************************************************************
228 template <typename T, TReturn(T::* Method)(TParams...) const, T const& Instance>
229 ETL_NODISCARD
234
235#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
236 //*************************************************************************
239 //*************************************************************************
240 template <typename T, T& Instance>
241 ETL_NODISCARD
242 static ETL_CONSTEXPR14 delegate create()
243 {
245 }
246#endif
247
248 //*************************************************************************
250 //*************************************************************************
251 template <TReturn(*Method)(TParams...)>
252 ETL_CONSTEXPR14 void set()
253 {
254 assign(ETL_NULLPTR, function_stub<Method>);
255 }
256
257 //*************************************************************************
259 //*************************************************************************
261 ETL_CONSTEXPR14 void set(TLambda& instance)
262 {
263 assign((void*)(&instance), lambda_stub<TLambda>);
264 }
265
266 //*************************************************************************
268 //*************************************************************************
270 ETL_CONSTEXPR14 void set(const TLambda& instance)
271 {
272 assign((void*)(&instance), const_lambda_stub<TLambda>);
273 }
274
275 //*************************************************************************
277 //*************************************************************************
278 template <typename T, TReturn(T::* Method)(TParams...)>
279 ETL_CONSTEXPR14 void set(T& instance)
280 {
281 assign((void*)(&instance), method_stub<T, Method>);
282 }
283
284 //*************************************************************************
286 //*************************************************************************
287 template <typename T, TReturn(T::* Method)(TParams...) const>
288 ETL_CONSTEXPR14 void set(T& instance)
289 {
290 assign((void*)(&instance), const_method_stub<T, Method>);
291 }
292
293 //*************************************************************************
295 //*************************************************************************
296 template <typename T, T& Instance, TReturn(T::* Method)(TParams...)>
297 ETL_CONSTEXPR14 void set()
298 {
300 }
301
302 //*************************************************************************
305 //*************************************************************************
306 template <typename T, TReturn(T::* Method)(TParams...), T& Instance>
307 ETL_CONSTEXPR14 void set()
308 {
310 }
311
312 //*************************************************************************
314 //*************************************************************************
315 template <typename T, T const& Instance, TReturn(T::* Method)(TParams...) const>
316 ETL_CONSTEXPR14 void set()
317 {
319 }
320
321 //*************************************************************************
324 //*************************************************************************
325 template <typename T, TReturn(T::* Method)(TParams...) const, T const& Instance>
326 ETL_CONSTEXPR14 void set()
327 {
329 }
330
331 //*************************************************************************
333 //*************************************************************************
334 ETL_CONSTEXPR14 void clear()
335 {
336 invocation.clear();
337 }
338
339 //*************************************************************************
341 //*************************************************************************
343 {
344 ETL_ASSERT(is_valid(), ETL_ERROR(delegate_uninitialised));
345
346 return (*invocation.stub)(invocation.object, etl::forward<TParams>(args)...);
347 }
348
349 //*************************************************************************
352 //*************************************************************************
353 template <typename TRet = TReturn>
354 ETL_CONSTEXPR14
357 {
358 if (is_valid())
359 {
360 (*invocation.stub)(invocation.object, etl::forward<TParams>(args)...);
361 return true;
362 }
363 else
364 {
365 return false;
366 }
367 }
368
369 //*************************************************************************
372 //*************************************************************************
373 template <typename TRet = TReturn>
374 ETL_CONSTEXPR14
377 {
379
380 if (is_valid())
381 {
382 result = (*invocation.stub)(invocation.object, etl::forward<TParams>(args)...);
383 }
384
385 return result;
386 }
387
388 //*************************************************************************
391 //*************************************************************************
392 template <typename TAlternative>
394 {
395 if (is_valid())
396 {
397 return (*invocation.stub)(invocation.object, etl::forward<TParams>(args)...);
398 }
399 else
400 {
402 }
403 }
404
405 //*************************************************************************
408 //*************************************************************************
409 template <TReturn(*Method)(TParams...)>
411 {
412 if (is_valid())
413 {
414 return (*invocation.stub)(invocation.object, etl::forward<TParams>(args)...);
415 }
416 else
417 {
418 return (Method)(etl::forward<TParams>(args)...);
419 }
420 }
421
422 //*************************************************************************
424 //*************************************************************************
425 delegate& operator =(const delegate& rhs) = default;
426
427 //*************************************************************************
429 //*************************************************************************
431 ETL_CONSTEXPR14 delegate& operator =(TLambda& instance)
432 {
433 assign((void*)(&instance), lambda_stub<TLambda>);
434 return *this;
435 }
436
437 //*************************************************************************
439 //*************************************************************************
441 ETL_CONSTEXPR14 delegate& operator =(const TLambda& instance)
442 {
443 assign((void*)(&instance), const_lambda_stub<TLambda>);
444 return *this;
445 }
446
447 //*************************************************************************
449 //*************************************************************************
450 ETL_CONSTEXPR14 bool operator == (const delegate& rhs) const
451 {
452 return invocation == rhs.invocation;
453 }
454
455 //*************************************************************************
457 //*************************************************************************
458 ETL_CONSTEXPR14 bool operator != (const delegate& rhs) const
459 {
460 return invocation != rhs.invocation;
461 }
462
463 //*************************************************************************
465 //*************************************************************************
466 ETL_NODISCARD
467 ETL_CONSTEXPR14 bool is_valid() const
468 {
469 return invocation.stub != ETL_NULLPTR;
470 }
471
472 //*************************************************************************
474 //*************************************************************************
475 ETL_CONSTEXPR14 operator bool() const
476 {
477 return is_valid();
478 }
479
480 private:
481
482 using stub_type = TReturn(*)(void* object, TParams...);
483
484 //*************************************************************************
486 //*************************************************************************
487 struct invocation_element
488 {
489 invocation_element() = default;
490
491 //***********************************************************************
492 ETL_CONSTEXPR14 invocation_element(void* object_, stub_type stub_)
493 : object(object_)
494 , stub(stub_)
495 {
496 }
497
498 //***********************************************************************
499 ETL_CONSTEXPR14 bool operator ==(const invocation_element& rhs) const
500 {
501 return (rhs.stub == stub) && (rhs.object == object);
502 }
503
504 //***********************************************************************
505 ETL_CONSTEXPR14 bool operator !=(const invocation_element& rhs) const
506 {
507 return (rhs.stub != stub) || (rhs.object != object);
508 }
509
510 //***********************************************************************
511 ETL_CONSTEXPR14 void clear()
512 {
513 object = ETL_NULLPTR;
514 stub = ETL_NULLPTR;
515 }
516
517 //***********************************************************************
518 void* object = ETL_NULLPTR;
519 stub_type stub = ETL_NULLPTR;
520 };
521
522 //*************************************************************************
524 //*************************************************************************
525 ETL_CONSTEXPR14 delegate(void* object, stub_type stub)
526 : invocation(object, stub)
527 {
528 }
529
530 //*************************************************************************
532 //*************************************************************************
533 ETL_CONSTEXPR14 delegate(stub_type stub)
534 : invocation(ETL_NULLPTR, stub)
535 {
536 }
537
538 //*************************************************************************
540 //*************************************************************************
541 ETL_CONSTEXPR14 void assign(void* object, stub_type stub)
542 {
543 invocation.object = object;
544 invocation.stub = stub;
545 }
546
547 //*************************************************************************
549 //*************************************************************************
550 template <typename T, TReturn(T::*Method)(TParams...)>
551 static ETL_CONSTEXPR14 TReturn method_stub(void* object, TParams... params)
552 {
553 T* p = static_cast<T*>(object);
554 return (p->*Method)(etl::forward<TParams>(params)...);
555 }
556
557 //*************************************************************************
559 //*************************************************************************
560 template <typename T, TReturn(T::*Method)(TParams...) const>
561 static ETL_CONSTEXPR14 TReturn const_method_stub(void* object, TParams... params)
562 {
563 T* const p = static_cast<T*>(object);
564 return (p->*Method)(etl::forward<TParams>(params)...);
565 }
566
567 //*************************************************************************
569 //*************************************************************************
570 template <typename T, TReturn(T::*Method)(TParams...), T& Instance>
571 static ETL_CONSTEXPR14 TReturn method_instance_stub(void*, TParams... params)
572 {
573 return (Instance.*Method)(etl::forward<TParams>(params)...);
574 }
575
576 //*************************************************************************
578 //*************************************************************************
579 template <typename T, TReturn(T::*Method)(TParams...) const, const T& Instance>
580 static ETL_CONSTEXPR14 TReturn const_method_instance_stub(void*, TParams... params)
581 {
582 return (Instance.*Method)(etl::forward<TParams>(params)...);
583 }
584
585#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
586 //*************************************************************************
588 //*************************************************************************
589 template <typename T, T& Instance>
590 static ETL_CONSTEXPR14 TReturn operator_instance_stub(void*, TParams... params)
591 {
592 return Instance.operator()(etl::forward<TParams>(params)...);
593 }
594#endif
595
596 //*************************************************************************
598 //*************************************************************************
599 template <TReturn(*Method)(TParams...)>
600 static ETL_CONSTEXPR14 TReturn function_stub(void*, TParams... params)
601 {
602 return (Method)(etl::forward<TParams>(params)...);
603 }
604
605 //*************************************************************************
607 //*************************************************************************
608 template <typename TLambda>
609 static ETL_CONSTEXPR14 TReturn lambda_stub(void* object, TParams... arg)
610 {
611 TLambda* p = static_cast<TLambda*>(object);
612 return (p->operator())(etl::forward<TParams>(arg)...);
613 }
614
615 //*************************************************************************
617 //*************************************************************************
618 template <typename TLambda>
619 static ETL_CONSTEXPR14 TReturn const_lambda_stub(void* object, TParams... arg)
620 {
621 const TLambda* p = static_cast<const TLambda*>(object);
622 return (p->operator())(etl::forward<TParams>(arg)...);
623 }
624
625 //*************************************************************************
627 //*************************************************************************
628 invocation_element invocation;
629 };
630}
631
632#endif
ETL_CONSTEXPR14 void set()
Set from function (Compile time).
Definition delegate_cpp11.h:252
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(const TLambda &instance)
Create from const Lambda or Functor.
Definition delegate_cpp11.h:154
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create()
Definition delegate_cpp11.h:242
ETL_CONSTEXPR14 etl::enable_if_t< etl::is_same< TRet, void >::value, bool > call_if(TParams... args) const
Definition delegate_cpp11.h:356
ETL_CONSTEXPR14 void set(const TLambda &instance)
Set from const Lambda or Functor.
Definition delegate_cpp11.h:270
ETL_CONSTEXPR14 void set(TLambda &instance)
Set from Lambda or Functor.
Definition delegate_cpp11.h:261
ETL_CONSTEXPR14 delegate()
Default constructor.
Definition delegate_cpp11.h:102
TReturn operator()(TParams... args) const
Execute the delegate.
Definition delegate_cpp11.h:342
ETL_CONSTEXPR14 void clear()
Clear the delegate.
Definition delegate_cpp11.h:334
TReturn call_or(TAlternative alternative, TParams... args) const
Definition delegate_cpp11.h:393
TReturn call_or(TParams... args) const
Definition delegate_cpp11.h:410
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(TLambda &instance)
Create from Lambda or Functor.
Definition delegate_cpp11.h:144
ETL_CONSTEXPR14 etl::enable_if_t<!etl::is_same< TRet, void >::value, etl::optional< TReturn > > call_if(TParams... args) const
Definition delegate_cpp11.h:376
ETL_NODISCARD ETL_CONSTEXPR14 bool is_valid() const
Returns true if the delegate is valid.
Definition delegate_cpp11.h:467
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create()
Create from function (Compile time).
Definition delegate_cpp11.h:134
The exception thrown when the delegate is uninitialised.
Definition delegate_cpp03.h:162
Declaration.
Definition delegate_cpp03.h:175
A templated set implementation that uses a fixed size buffer.
Definition set.h:2548
ETL_CONSTEXPR14 bool operator==(const etl::expected< TValue, TError > &lhs, const etl::expected< TValue2, TError2 > &rhs)
Equivalence operators.
Definition expected.h:966
#define ETL_ASSERT(b, e)
Definition error_handler.h:316
ETL_CONSTEXPR exception(string_type reason_, string_type, numeric_type line_)
Constructor.
Definition exception.h:69
is_same
Definition type_traits_generator.h:1041
bitset_ext
Definition absolute.h:38
T * create(Args &&... args)
Creates the object from a type. Variadic parameter constructor.
Definition variant_pool_generator.h:348
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:654
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:642
pair holds two objects of arbitrary type
Definition utility.h:164