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 //*************************************************************************
205 //*************************************************************************
206 template <typename T, T const& Instance, TReturn(T::*Method)(TParams...) const>
207 ETL_NODISCARD
212
213#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
214 //*************************************************************************
217 //*************************************************************************
218 template <typename T, T& Instance>
219 ETL_NODISCARD
220 static ETL_CONSTEXPR14 delegate create()
221 {
223 }
224#endif
225
226 //*************************************************************************
228 //*************************************************************************
229 template <TReturn(*Method)(TParams...)>
230 ETL_CONSTEXPR14 void set()
231 {
232 assign(ETL_NULLPTR, function_stub<Method>);
233 }
234
235 //*************************************************************************
237 //*************************************************************************
239 ETL_CONSTEXPR14 void set(TLambda& instance)
240 {
241 assign((void*)(&instance), lambda_stub<TLambda>);
242 }
243
244 //*************************************************************************
246 //*************************************************************************
248 ETL_CONSTEXPR14 void set(const TLambda& instance)
249 {
250 assign((void*)(&instance), const_lambda_stub<TLambda>);
251 }
252
253 //*************************************************************************
255 //*************************************************************************
256 template <typename T, TReturn(T::* Method)(TParams...)>
257 ETL_CONSTEXPR14 void set(T& instance)
258 {
259 assign((void*)(&instance), method_stub<T, Method>);
260 }
261
262 //*************************************************************************
264 //*************************************************************************
265 template <typename T, TReturn(T::* Method)(TParams...) const>
266 ETL_CONSTEXPR14 void set(T& instance)
267 {
268 assign((void*)(&instance), const_method_stub<T, Method>);
269 }
270
271 //*************************************************************************
273 //*************************************************************************
274 template <typename T, T& Instance, TReturn(T::* Method)(TParams...)>
275 ETL_CONSTEXPR14 void set()
276 {
278 }
279
280 //*************************************************************************
282 //*************************************************************************
283 template <typename T, T const& Instance, TReturn(T::* Method)(TParams...) const>
284 ETL_CONSTEXPR14 void set()
285 {
287 }
288
289 //*************************************************************************
291 //*************************************************************************
292 ETL_CONSTEXPR14 void clear()
293 {
294 invocation.clear();
295 }
296
297 //*************************************************************************
299 //*************************************************************************
301 {
302 ETL_ASSERT(is_valid(), ETL_ERROR(delegate_uninitialised));
303
304 return (*invocation.stub)(invocation.object, etl::forward<TParams>(args)...);
305 }
306
307 //*************************************************************************
310 //*************************************************************************
311 template <typename TRet = TReturn>
314 {
315 if (is_valid())
316 {
317 (*invocation.stub)(invocation.object, etl::forward<TParams>(args)...);
318 return true;
319 }
320 else
321 {
322 return false;
323 }
324 }
325
326 //*************************************************************************
329 //*************************************************************************
330 template <typename TRet = TReturn>
333 {
335
336 if (is_valid())
337 {
338 result = (*invocation.stub)(invocation.object, etl::forward<TParams>(args)...);
339 }
340
341 return result;
342 }
343
344 //*************************************************************************
347 //*************************************************************************
348 template <typename TAlternative>
350 {
351 if (is_valid())
352 {
353 return (*invocation.stub)(invocation.object, etl::forward<TParams>(args)...);
354 }
355 else
356 {
358 }
359 }
360
361 //*************************************************************************
364 //*************************************************************************
365 template <TReturn(*Method)(TParams...)>
367 {
368 if (is_valid())
369 {
370 return (*invocation.stub)(invocation.object, etl::forward<TParams>(args)...);
371 }
372 else
373 {
374 return (Method)(etl::forward<TParams>(args)...);
375 }
376 }
377
378 //*************************************************************************
380 //*************************************************************************
381 delegate& operator =(const delegate& rhs) = default;
382
383 //*************************************************************************
385 //*************************************************************************
387 ETL_CONSTEXPR14 delegate& operator =(TLambda& instance)
388 {
389 assign((void*)(&instance), lambda_stub<TLambda>);
390 return *this;
391 }
392
393 //*************************************************************************
395 //*************************************************************************
397 ETL_CONSTEXPR14 delegate& operator =(const TLambda& instance)
398 {
399 assign((void*)(&instance), const_lambda_stub<TLambda>);
400 return *this;
401 }
402
403 //*************************************************************************
405 //*************************************************************************
406 ETL_CONSTEXPR14 bool operator == (const delegate& rhs) const
407 {
408 return invocation == rhs.invocation;
409 }
410
411 //*************************************************************************
413 //*************************************************************************
414 ETL_CONSTEXPR14 bool operator != (const delegate& rhs) const
415 {
416 return invocation != rhs.invocation;
417 }
418
419 //*************************************************************************
421 //*************************************************************************
422 ETL_NODISCARD
423 ETL_CONSTEXPR14 bool is_valid() const
424 {
425 return invocation.stub != ETL_NULLPTR;
426 }
427
428 //*************************************************************************
430 //*************************************************************************
431 ETL_CONSTEXPR14 operator bool() const
432 {
433 return is_valid();
434 }
435
436 private:
437
438 using stub_type = TReturn(*)(void* object, TParams...);
439
440 //*************************************************************************
442 //*************************************************************************
443 struct invocation_element
444 {
445 invocation_element() = default;
446
447 //***********************************************************************
448 ETL_CONSTEXPR14 invocation_element(void* object_, stub_type stub_)
449 : object(object_)
450 , stub(stub_)
451 {
452 }
453
454 //***********************************************************************
455 ETL_CONSTEXPR14 bool operator ==(const invocation_element& rhs) const
456 {
457 return (rhs.stub == stub) && (rhs.object == object);
458 }
459
460 //***********************************************************************
461 ETL_CONSTEXPR14 bool operator !=(const invocation_element& rhs) const
462 {
463 return (rhs.stub != stub) || (rhs.object != object);
464 }
465
466 //***********************************************************************
467 ETL_CONSTEXPR14 void clear()
468 {
469 object = ETL_NULLPTR;
470 stub = ETL_NULLPTR;
471 }
472
473 //***********************************************************************
474 void* object = ETL_NULLPTR;
475 stub_type stub = ETL_NULLPTR;
476 };
477
478 //*************************************************************************
480 //*************************************************************************
481 ETL_CONSTEXPR14 delegate(void* object, stub_type stub)
482 : invocation(object, stub)
483 {
484 }
485
486 //*************************************************************************
488 //*************************************************************************
489 ETL_CONSTEXPR14 delegate(stub_type stub)
490 : invocation(ETL_NULLPTR, stub)
491 {
492 }
493
494 //*************************************************************************
496 //*************************************************************************
497 ETL_CONSTEXPR14 void assign(void* object, stub_type stub)
498 {
499 invocation.object = object;
500 invocation.stub = stub;
501 }
502
503 //*************************************************************************
505 //*************************************************************************
506 template <typename T, TReturn(T::*Method)(TParams...)>
507 static ETL_CONSTEXPR14 TReturn method_stub(void* object, TParams... params)
508 {
509 T* p = static_cast<T*>(object);
510 return (p->*Method)(etl::forward<TParams>(params)...);
511 }
512
513 //*************************************************************************
515 //*************************************************************************
516 template <typename T, TReturn(T::*Method)(TParams...) const>
517 static ETL_CONSTEXPR14 TReturn const_method_stub(void* object, TParams... params)
518 {
519 T* const p = static_cast<T*>(object);
520 return (p->*Method)(etl::forward<TParams>(params)...);
521 }
522
523 //*************************************************************************
525 //*************************************************************************
526 template <typename T, T& Instance, TReturn(T::*Method)(TParams...)>
527 static ETL_CONSTEXPR14 TReturn method_instance_stub(void*, TParams... params)
528 {
529 return (Instance.*Method)(etl::forward<TParams>(params)...);
530 }
531
532 //*************************************************************************
534 //*************************************************************************
535 template <typename T, const T& Instance, TReturn(T::*Method)(TParams...) const>
536 static ETL_CONSTEXPR14 TReturn const_method_instance_stub(void*, TParams... params)
537 {
538 return (Instance.*Method)(etl::forward<TParams>(params)...);
539 }
540
541#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
542 //*************************************************************************
544 //*************************************************************************
545 template <typename T, T& Instance>
546 static ETL_CONSTEXPR14 TReturn operator_instance_stub(void*, TParams... params)
547 {
548 return Instance.operator()(etl::forward<TParams>(params)...);
549 }
550#endif
551
552 //*************************************************************************
554 //*************************************************************************
555 template <TReturn(*Method)(TParams...)>
556 static ETL_CONSTEXPR14 TReturn function_stub(void*, TParams... params)
557 {
558 return (Method)(etl::forward<TParams>(params)...);
559 }
560
561 //*************************************************************************
563 //*************************************************************************
564 template <typename TLambda>
565 static ETL_CONSTEXPR14 TReturn lambda_stub(void* object, TParams... arg)
566 {
567 TLambda* p = static_cast<TLambda*>(object);
568 return (p->operator())(etl::forward<TParams>(arg)...);
569 }
570
571 //*************************************************************************
573 //*************************************************************************
574 template <typename TLambda>
575 static ETL_CONSTEXPR14 TReturn const_lambda_stub(void* object, TParams... arg)
576 {
577 const TLambda* p = static_cast<const TLambda*>(object);
578 return (p->operator())(etl::forward<TParams>(arg)...);
579 }
580
581 //*************************************************************************
583 //*************************************************************************
584 invocation_element invocation;
585 };
586}
587
588#endif
ETL_CONSTEXPR14 void set()
Set from function (Compile time).
Definition delegate_cpp11.h:230
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:220
etl::enable_if_t<!etl::is_same< TRet, void >::value, etl::optional< TReturn > > call_if(TParams... args) const
Definition delegate_cpp11.h:332
ETL_CONSTEXPR14 void set(const TLambda &instance)
Set from const Lambda or Functor.
Definition delegate_cpp11.h:248
ETL_CONSTEXPR14 void set(TLambda &instance)
Set from Lambda or Functor.
Definition delegate_cpp11.h:239
ETL_CONSTEXPR14 delegate()
Default constructor.
Definition delegate_cpp11.h:102
TReturn operator()(TParams... args) const
Execute the delegate.
Definition delegate_cpp11.h:300
ETL_CONSTEXPR14 void clear()
Clear the delegate.
Definition delegate_cpp11.h:292
etl::enable_if_t< etl::is_same< TRet, void >::value, bool > call_if(TParams... args) const
Definition delegate_cpp11.h:313
TReturn call_or(TAlternative alternative, TParams... args) const
Definition delegate_cpp11.h:349
TReturn call_or(TParams... args) const
Definition delegate_cpp11.h:366
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(TLambda &instance)
Create from Lambda or Functor.
Definition delegate_cpp11.h:144
ETL_NODISCARD ETL_CONSTEXPR14 bool is_valid() const
Returns true if the delegate is valid.
Definition delegate_cpp11.h:423
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:2502
ETL_CONSTEXPR14 bool operator==(const etl::unexpected< TError > &lhs, const etl::unexpected< TError > &rhs)
Equivalence operator.
Definition expected.h:950
#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:234
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:645
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:633
pair holds two objects of arbitrary type
Definition utility.h:164
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:1017