jaulib v1.3.6
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
functional3.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020-2022 Gothel Software e.K.
4 * Copyright (c) 2020 ZAFENA AB
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#ifndef JAU_FUNCTIONAL_HPP_
27#define JAU_FUNCTIONAL_HPP_
28
29#include <cstring>
30#include <string>
31#include <memory>
32#include <cstdint>
33#include <type_traits>
34#include <functional>
35
36#include <jau/basic_types.hpp>
37#include <jau/cpp_lang_util.hpp>
38
39namespace jau {
40
41 namespace func {
42
43 /** \addtogroup FunctionWrap
44 *
45 * @{
46 */
47
48 /**
49 * func::target_type identifier for specializations of func::target_t
50 * used by jau::function<R(A...)>::type().
51 *
52 * @see @ref function_overview "Function Overview"
53 */
54 enum class target_type : uint32_t {
55 /** Denotes a func::null_target_t */
56 null = 0,
57 /** Denotes a func::member_target_t */
58 member = 1,
59 /** Denotes a func::free_target_t */
60 free = 2,
61 /** Denotes a func::lambda_target_t */
62 lambda = 3,
63 /** Denotes a func::capval_target_t */
64 capval = 4,
65 /** Denotes a func::capref_target_t */
66 capref = 5,
67 /** Denotes a func::std_target_t */
68 std = 6
69 };
70
71 /**
72 * func::target_t pure-virtual interface for [jau::function](@ref function_def).
73 *
74 * @tparam R function return type
75 * @tparam A function arguments
76 * @see @ref function_overview "Function Overview"
77 */
78 template<typename R, typename... A>
79 class target_t {
80 private:
81 target_type ttype;
82
83 protected:
84 target_t(target_type ttype_) noexcept
85 : ttype(ttype_) {}
86
87 public:
88 virtual ~target_t() noexcept {}
89
90 target_t(const target_t &o) noexcept = default;
91 target_t(target_t &&o) noexcept = default;
92 target_t& operator=(const target_t &o) noexcept = default;
93 target_t& operator=(target_t &&o) noexcept = default;
94
95 /** Return the func::target_type of this invocation function wrapper */
96 constexpr target_type type() const noexcept { return ttype; }
97
98 virtual R operator()(A... args) = 0;
99 virtual bool operator==(const target_t<R, A...>& rhs) const noexcept = 0;
100 };
101
102 /**
103 * func::null_target_t implementation for no function.
104 * identifiable as jau::func::target_type::null via jau::function<R(A...)>::type().
105 *
106 * This special type is used for an empty [jau::function](@ref function_def) instance w/o holding a function,
107 * e.g. when created with the default constructor.
108 *
109 * @tparam R function return type
110 * @tparam A function arguments
111 * @see @ref function_overview "Function Overview"
112 */
113 template<typename R, typename... A>
114 class null_target_t final : public target_t<R, A...> {
115 public:
116 null_target_t() noexcept
117 : target_t<R, A...>( target_type::null )
118 { }
119
120 R operator()(A...) override {
121 return R();
122 }
123
124 bool operator==(const target_t<R, A...>& rhs) const noexcept override {
125 return target_t<R, A...>::type() == rhs.type();
126 }
127 };
128
129 /**
130 * func::member_target_t implementation for class member functions,
131 * identifiable as func::target_type::member via jau::function<R(A...)>::type().
132 *
133 * @tparam R function return type
134 * @tparam C0 class type holding the member-function
135 * @tparam C1 class derived from C0 or C0 of this base-pointer used to invoke the member-function
136 * @tparam A function arguments
137 * @see @ref function_overview "Function Overview"
138 */
139 template<typename R, typename C0, typename C1, typename... A>
140 class member_target_t final : public target_t<R, A...> {
141 private:
142 C1* base;
143 R(C0::*member)(A...);
144
145 public:
146 /**
147 * Construct a target_t<R, A...> instance from given this base-pointer and member-function.
148 *
149 * This factory function is only enabled if C0 is base of C1.
150 *
151 * @param _base this base-pointer of class C1 derived from C0 or C0 used to invoke the member-function
152 * @param _member member-function of class C0
153 * @return target_t<R, A...> instance holding the target-function details.
154 */
155 member_target_t(C1 *_base, R(C0::*_member)(A...),
156 std::enable_if_t<std::is_base_of_v<C0, C1>, bool> = true) noexcept
157 : target_t<R, A...>( target_type::member ),
158 base(_base), member(_member) { }
159
160 R operator()(A... args) override {
161 return (base->*member)(args...);
162 }
163
164 bool operator==(const target_t<R, A...>& rhs) const noexcept override {
165 const member_target_t<R, C0, C1, A...>* prhs = static_cast<const member_target_t<R, C0, C1, A...>*>(&rhs);
166 return this == prhs ||
167 ( target_t<R, A...>::type() == rhs.type() &&
168 base == prhs->base &&
169 member == prhs->member
170 );
171 }
172 };
173
174 /**
175 * func::free_target_t implementation for free functions,
176 * identifiable as func::target_type::free via jau::function<R(A...)>::type().
177 *
178 * @tparam R function return type
179 * @tparam A function arguments
180 * @see @ref function_overview "Function Overview"
181 */
182 template<typename R, typename... A>
183 class free_target_t final : public target_t<R, A...> {
184 private:
185 R(*function)(A...);
186
187 public:
188 free_target_t(R(*_function)(A...)) noexcept
189 : target_t<R, A...>( target_type::free ),
190 function(_function) { }
191
192 R operator()(A... args) override {
193 return (*function)(args...);
194 }
195
196 bool operator==(const target_t<R, A...>& rhs) const noexcept override {
197 const free_target_t<R, A...>* prhs = static_cast<const free_target_t<R, A...>*>(&rhs);
198 return this == prhs ||
199 ( target_t<R, A...>::type() == rhs.type() &&
200 function == prhs->function
201 );
202 }
203 };
204
205 /**
206 * func::lambda_target_t implementation for lambda closures,
207 * identifiable as func::target_type::lambda via jau::function<R(A...)>::type().
208 *
209 * @tparam R function return type
210 * @tparam L typename holding the lambda closure
211 * @tparam A function arguments
212 * @see @ref function_overview "Function Overview"
213 */
214 template<typename R, typename L, typename...A>
215 class lambda_target_t final : public target_t<R, A...>
216 {
217 private:
218 jau::type_info sig;
219 L function;
220
221 constexpr size_t detail_size() const noexcept { return sizeof(function); }
222
223 public:
224 lambda_target_t(L function_) noexcept
225 : target_t<R, A...>( target_type::lambda ),
226 sig( jau::make_ctti<R, L, A...>() ), function(function_)
227 { }
228
229 R operator()(A... args) override {
230 return function(args...);
231 }
232
233 bool operator==(const target_t<R, A...>& rhs) const noexcept override {
234 const lambda_target_t<R, L, A...>* prhs = static_cast<const lambda_target_t<R, L, A...>*>(&rhs);
235 return this == prhs ||
236 ( target_t<R, A...>::type() == rhs.type() &&
237 detail_size() == prhs->detail_size() && // fast: wrong size -> false, otherwise ...
238 sig == prhs->sig && // mixed: wrong jau::type_info -> false, otherwise ...
239 0 == ::memcmp((void*)&function, (void*)&prhs->function, sizeof(function)) // slow: compare the anonymous data chunk of the lambda
240 );
241 }
242 };
243
244 /**
245 * func::capval_target_t implementation for functions using a copy of a captured value,
246 * identifiable as func::target_type::capval via jau::function<R(A...)>::type().
247 *
248 * @tparam R function return type
249 * @tparam I typename holding the captured data used by the function
250 * @tparam A function arguments
251 * @see @ref function_overview "Function Overview"
252 */
253 template<typename R, typename I, typename... A>
254 class capval_target_t final : public target_t<R, A...> {
255 private:
256 R(*function)(I&, A...);
257 I data;
258
259 public:
260 /** Utilizes copy-ctor from 'const I& _data' */
261 capval_target_t(const I& _data, R(*_function)(I&, A...)) noexcept
262 : target_t<R, A...>( target_type::capval ),
263 function(_function), data(_data) { }
264
265 /** Utilizes move-ctor from moved 'I&& _data' */
266 capval_target_t(I&& _data, R(*_function)(I&, A...)) noexcept
267 : target_t<R, A...>( target_type::capval ),
268 function(_function), data(std::move(_data)) { }
269
270 R operator()(A... args) override {
271 return (*function)(data, args...);
272 }
273
274 bool operator==(const target_t<R, A...>& rhs) const noexcept override {
275 const capval_target_t<R, I, A...>* prhs = static_cast<const capval_target_t<R, I, A...>*>(&rhs);
276 return this == prhs ||
277 ( target_t<R, A...>::type() == rhs.type() &&
278 function == prhs->function &&
279 data == prhs->data
280 );
281 }
282 };
283
284 /**
285 * func::capref_target_t implementation for functions using a reference to a captured value,
286 * identifiable as func::target_type::capref via jau::function<R(A...)>::type().
287 *
288 * @tparam R function return type
289 * @tparam I typename holding the captured data used by the function
290 * @tparam A function arguments
291 * @see @ref function_overview "Function Overview"
292 */
293 template<typename R, typename I, typename... A>
294 class capref_target_t final : public target_t<R, A...> {
295 private:
296 R(*function)(I*, A...);
297 I* data_ptr;
298
299 public:
300 capref_target_t(I* _data_ptr, R(*_function)(I*, A...)) noexcept
301 : target_t<R, A...>( target_type::capref ),
302 function(_function), data_ptr(_data_ptr) { }
303
304 R operator()(A... args) override {
305 return (*function)(data_ptr, args...);
306 }
307
308 bool operator==(const target_t<R, A...>& rhs) const noexcept override {
309 const capref_target_t<R, I, A...>* prhs = static_cast<const capref_target_t<R, I, A...>*>(&rhs);
310 return this == prhs ||
311 ( target_t<R, A...>::type() == rhs.type() &&
312 function == prhs->function &&
313 data_ptr == prhs->data_ptr
314 );
315 }
316 };
317
318 /**
319 * func::std_target_t implementation for std::function instances,
320 * identifiable as func::target_type::std via jau::function<R(A...)>::type().
321 *
322 * Notable, instance is holding a unique uint64_t identifier
323 * to allow implementing the equality operator, not supported by std::function.
324 *
325 * @tparam R function return type
326 * @tparam A function arguments
327 * @see @ref function_overview "Function Overview"
328 */
329 template<typename R, typename... A>
330 class std_target_t : public target_t<R, A...> {
331 private:
332 uint64_t id;
333 std::function<R(A...)> function;
334
335 constexpr size_t detail_size() const noexcept { return sizeof(id)+sizeof(function); }
336
337 public:
338 std_target_t(uint64_t _id, std::function<R(A...)> _function) noexcept
339 : target_t<R, A...>( target_type::std ),
340 id(_id), function(_function) { }
341
342 std_target_t(uint64_t _id) noexcept
343 : target_t<R, A...>( target_type::std ),
344 id(_id), function() { }
345
346 R operator()(A... args) override {
347 return function(args...);
348 }
349
350 bool operator==(const target_t<R, A...>& rhs) const noexcept override {
351 const std_target_t<R, A...>* prhs = static_cast<const std_target_t<R, A...>*>(&rhs);
352 return this == prhs ||
353 ( target_t<R, A...>::type() == rhs.type() &&
354 id == prhs->id &&
355 detail_size() && prhs->detail_size()
356 );
357 }
358 };
359
360 /**@}*/
361
362 } /* namespace func */
363
364 constexpr uint32_t number(const func::target_type rhs) noexcept {
365 return static_cast<uint32_t>(rhs);
366 }
367 std::string to_string(const func::target_type v) noexcept;
368
369 /**
370 * Class template [jau::function](@ref function_def) is a general-purpose polymorphic function wrapper.
371 *
372 * See @ref function_overview "Function Overview".
373 *
374 * This is the dummy template variant, allowing the void- and non-void return type target specializations.
375 *
376 * @see @ref function_def "Function template definition"
377 */
378 template<typename Signature>
379 class function;
380
381 /**
382 * @anchor function_def
383 * Class template [jau::function](@ref function_def) is a general-purpose polymorphic function wrapper.
384 *
385 * See @ref function_overview "Function Overview".
386 *
387 * @tparam R function return type
388 * @tparam A function arguments
389 * @see @ref function_overview "Function Overview"
390 * @see @ref function_usage "Function Usage"
391 */
392 template<typename R, typename... A>
393 class function<R(A...)> final {
394 public:
395 /** The target function type, i.e. func::target_t<R, A...> */
396 typedef func::target_t<R, A...> target_type;
397
398 private:
399 std::shared_ptr<target_type> target_func;
400 size_t target_func_size;
401
402 public:
403 /** The target function return type R */
404 typedef R result_type;
405
406 /**
407 * \brief Null function constructor
408 *
409 * @anchor function_ctor_def
410 * Constructs an instance with a null target function.
411 * @see @ref function_overview "function Overview"
412 * @see @ref function_usage "function Usage"
413 */
414 function() noexcept
415 : target_func( std::make_shared<func::null_target_t<R, A...>>() ),
416 target_func_size( sizeof(func::null_target_t<R, A...>))
417 { }
418
419 /**
420 * \brief Null function constructor
421 *
422 * @anchor function_ctor_nullptr
423 * Constructs an instance with a null target function.
424 * @see @ref function_overview "function Overview"
425 * @see @ref function_usage "function Usage"
426 */
427 function(std::nullptr_t ) noexcept
428 : target_func( std::make_shared<func::null_target_t<R, A...>>() ),
429 target_func_size( sizeof(func::null_target_t<R, A...>))
430 { }
431
432 /**
433 * \brief target_type constructor
434 *
435 * @anchor function_ctor_target_type
436 * Constructs an instance with the given shared target function pointer.
437 * @see @ref function_overview "function Overview"
438 * @see @ref function_usage "function Usage"
439 */
440 explicit function(std::shared_ptr<target_type> _funcPtr, size_t asize_) noexcept
441 : target_func( _funcPtr ),
442 target_func_size( asize_ )
443 { }
444
445 /**
446 * \brief Free function constructor
447 *
448 * @anchor function_ctor_free
449 * Constructs an instance by taking a free target function, which may also be a non-capturing lambda if explicitly bind_free().
450 * @see @ref function_overview "function Overview"
451 * @see @ref function_usage "function Usage"
452 */
453 function(R(*func)(A...)) noexcept
454 : target_func( std::make_shared<func::free_target_t<R, A...>>(func) ),
455 target_func_size( sizeof(func::free_target_t<R, A...>))
456 { }
457
458 /**
459 * \brief Lambda function constructor
460 *
461 * @anchor function_ctor_lambda
462 * Constructs an instance by taking a lambda function.
463 * @tparam L typename holding the lambda closure
464 * @param func the lambda reference
465 * @see @ref function_overview "function Overview"
466 * @see @ref function_usage "function Usage"
467 */
468 template<typename L,
469 std::enable_if_t<!std::is_same_v<L, std::shared_ptr<target_type>> &&
470 !std::is_pointer_v<L> &&
471 !std::is_same_v<L, R(A...)> &&
472 !std::is_same_v<L, function<R(A...)>>
473 , bool> = true>
474 function(L func) noexcept
475 : target_func( std::make_shared<func::lambda_target_t<R, L, A...>>(func) ),
476 target_func_size( sizeof(func::lambda_target_t<R, L, A...>))
477 { }
478
479 /**
480 * \brief Member function constructor
481 *
482 * \anchor function_ctor_member
483 * Constructs an instance by taking a member target function.
484 * @tparam C0 class type holding the member-function
485 * @tparam C1 class derived from C0 or C0 of this base-pointer used to invoke the member-function
486 * @param base pointer to the class instance of the member function
487 * @param mfunc member function of class
488 * @see @ref function_overview "function Overview"
489 * @see @ref function_usage "function Usage"
490 */
491 template<typename C0, typename C1>
492 function(C1 *base, R(C0::*mfunc)(A...)) noexcept
493 : target_func( std::make_shared<func::member_target_t<R, C0, C1, A...>>(base, mfunc) ),
494 target_func_size( sizeof(func::member_target_t<R, C0, C1, A...>))
495 { }
496
497 /**
498 * \brief Capture by value (copy) function constructor
499 *
500 * @anchor function_ctor_capval_copy
501 * Constructs an instance by copying the captured value and the given non-void function to
502 * an anonymous function using func::capval_target_t.
503 *
504 * `const I& data` will be copied into func::capval_target_t and hence captured by copy.
505 *
506 * The function invocation will have the reference of the copied data being passed to the target function for efficiency.
507 *
508 * @tparam I typename holding the captured data used by the function
509 * @param data data type instance holding the captured data
510 * @param func function with `R` return value and `A...` arguments.
511 * @see @ref function_overview "function Overview"
512 * @see @ref function_usage "function Usage"
513 */
514 template<typename I>
515 function(const I& data, R(*func)(I&, A...)) noexcept
516 : target_func( std::make_shared<func::capval_target_t<R, I, A...>>(data, func) ),
517 target_func_size( sizeof(func::capval_target_t<R, I, A...>))
518 { }
519
520 /**
521 * \brief Capture by value (move) function constructor
522 *
523 * @anchor function_ctor_capval_move
524 * Constructs an instance by moving the captured value and copying the given non-void function to
525 * an anonymous function using func::capval_target_t.
526 *
527 * `I&& data` will be moved into func::capval_target_t.
528 *
529 * The function invocation will have the reference of the moved data being passed to the target function for efficiency.
530 *
531 * @tparam I typename holding the captured data used by the function
532 * @param data data type instance holding the captured data
533 * @param func function with `R` return value and `A...` arguments.
534 * @see @ref function_overview "function Overview"
535 * @see @ref function_usage "function Usage"
536 */
537 template<typename I>
538 function(I&& data, R(*func)(I&, A...)) noexcept
539 : target_func( std::make_shared<func::capval_target_t<R, I, A...>>(std::move(data), func) ),
540 target_func_size( sizeof(func::capval_target_t<R, I, A...>))
541 { }
542
543 /**
544 * \brief Capture by reference function constructor
545 *
546 * @anchor function_ctor_capref
547 * Constructs an instance by passing the captured reference (pointer) to the value and non-void function to
548 * an anonymous function using func::capref_target_t.
549 *
550 * The function invocation will have the reference of the data being passed to the target function.
551 *
552 * @tparam I typename holding the captured data used by the function
553 * @param data_ptr data type reference to instance holding the captured data
554 * @param func function with `R` return value and `A...` arguments.
555 * @see @ref function_overview "function Overview"
556 * @see @ref function_usage "function Usage"
557 */
558 template<typename I>
559 function(I* data_ptr, R(*func)(I*, A...)) noexcept
560 : target_func( std::make_shared<func::capref_target_t<R, I, A...>>(data_ptr, func) ),
561 target_func_size( sizeof(func::capref_target_t<R, I, A...>))
562 { }
563
564 /**
565 * \brief std::function constructor
566 *
567 * @anchor function_ctor_std
568 * Constructs an instance by copying the std::function to
569 * an anonymous function using func::std_target_t.
570 *
571 * Notable, instance is holding the given unique uint64_t identifier
572 * to allow implementing the equality operator w/o RTTI, not supported by std::function.
573 *
574 * @param func free-function with `R` return value and `A...` arguments.
575 * @see @ref function_overview "function Overview"
576 * @see @ref function_usage "function Usage"
577 */
578 function(uint64_t id, std::function<R(A...)> func) noexcept
579 : target_func( std::make_shared<func::std_target_t<R, A...>>(id, func) ),
580 target_func_size( sizeof(func::std_target_t<R, A...>))
581 { }
582
583 function(const function &o) noexcept = default;
584 function(function &&o) noexcept = default;
585 function& operator=(const function &o) noexcept = default;
586 function& operator=(function &&o) noexcept = default;
587
588 /** Return the jau::func::type of this instance */
589 constexpr func::target_type type() const noexcept { return target_func->type(); }
590
591 /** Returns true if this instance does not hold a callable target function, i.e. is of func::target_type::null. */
592 constexpr bool is_null() const noexcept { return func::target_type::null == target_func->type(); }
593
594 /** Returns true if this instance holds a callable target function, i.e. is not of func::target_type::null. */
595 explicit constexpr operator bool() const noexcept { return !is_null(); }
596
597 /** Returns signature of this function prototype R(A...) w/o underlying target function details. */
598 jau::type_info signature() const noexcept {
599 return jau::make_ctti<R(A...)>();
600 }
601
602 /** Returns the size of the target type */
603 constexpr size_t target_size() const noexcept { return target_func_size; }
604
605 std::string toString() const {
606 return "function<" + to_string( type() ) + ", " + signature().name() + ">( sz target_data " +
607 std::to_string( target_func_size ) + " + shared_ptr " +
608 std::to_string( sizeof( target_func ) ) + " + extra " +
609 std::to_string( sizeof( target_func_size ) ) + " -> " +
610 std::to_string( sizeof( *this ) + target_func_size ) + " ) ";
611 }
612
613 constexpr R operator()(A... args) const {
614 return (*target_func)(args...);
615 }
616 constexpr R operator()(A... args) {
617 return (*target_func)(args...);
618 }
619
620 constexpr bool operator==(const function<R(A...)>& rhs) const noexcept {
621 return target_func->operator==(*rhs.target_func);
622 }
623 constexpr bool operator!=(const function<R(A...)>& rhs) const noexcept {
624 return !operator==(rhs);
625 }
626 };
627
628 /**
629 * Equal operator using different jau::function<R(A...)> return and argument types for both arguments,
630 * always returns false.
631 * @tparam Rl left function return type
632 * @tparam Al left function arguments
633 * @tparam Fl left function Fl<Rl(<Al...)>
634 * @tparam Rr right function return type
635 * @tparam Ar right function arguments
636 * @tparam Fr right function Fr<Rr(<Ar...)>
637 * @param lhs left function Fl<Rl(<Al...)>
638 * @param rhs right function Fr<Rr(<Ar...)>
639 * @return false
640 * @see @ref function_overview "function Overview"
641 * @see @ref function_usage "function Usage"
642 */
643 template<typename Rl, typename... Al, template <typename...> class Fl = function,
644 typename Rr, typename... Ar, template <typename...> class Fr = function,
645 std::enable_if_t< !std::is_same_v< Fl<Rl(Al...)>, Fr<Rr(Ar...)> >
646 , bool> = true>
647 bool operator==(const function<Rl(Al...)>& lhs, const function<Rr(Ar...)>& rhs) noexcept
648 {
649 (void)lhs;
650 (void)rhs;
651 return false;
652 }
653
654 /**
655 * Equal operator using same jau::function<R(A...)> return and argument types for both arguments,
656 * returning actual result of equality operation.
657 * @tparam Rl left function return type
658 * @tparam Al left function arguments
659 * @tparam Fl left function Fl<Rl(<Al...)>
660 * @tparam Rr right function return type
661 * @tparam Ar right function arguments
662 * @tparam Fr right function Fr<Rr(<Ar...)>
663 * @param lhs left function Fl<Rl(<Al...)>
664 * @param rhs right function Fr<Rr(<Ar...)>
665 * @return equality result of same type functions
666 * @see @ref function_overview "function Overview"
667 * @see @ref function_usage "function Usage"
668 */
669 template<typename Rl, typename... Al, template <typename...> class Fl = function,
670 typename Rr, typename... Ar, template <typename...> class Fr = function,
671 std::enable_if_t< std::is_same_v< Fl<Rl(Al...)>, Fr<Rr(Ar...)> >
672 , bool> = true>
673 bool operator==(const function<Rl(Al...)>& lhs, const function<Rr(Ar...)>& rhs) noexcept
674 { return lhs.operator==( rhs ); }
675
676 /**
677 * Unequal operator using two jau::function<R(A...)> types for both arguments.
678 * @tparam Rl left function return type
679 * @tparam Al left function arguments
680 * @tparam Fl left function Fl<Rl(<Al...)>
681 * @tparam Rr right function return type
682 * @tparam Ar right function arguments
683 * @tparam Fr right function Fr<Rr(<Ar...)>
684 * @param lhs left function Fl<Rl(<Al...)>
685 * @param rhs right function Fr<Rr(<Ar...)>
686 * @return unequality result of same type functions
687 * @see @ref function_overview "function Overview"
688 * @see @ref function_usage "function Usage"
689 */
690 template<typename Rl, typename... Al, template <typename...> typename Fl = function,
691 typename Rr, typename... Ar, template <typename...> typename Fr = function>
692 bool operator!=(const function<Rl(Al...)>& lhs, const function<Rr(Ar...)>& rhs) noexcept
693 { return !( lhs == rhs ); }
694
695 /**
696 * Bind given class instance and non-void member function to
697 * an anonymous function using func_member_targer_t.
698 *
699 * @tparam R function return type
700 * @tparam C0 class type holding the member-function
701 * @tparam C1 class derived from C0 or C0 of this base-pointer used to invoke the member-function
702 * @tparam A function arguments
703 * @param base class instance `this` pointer
704 * @param mfunc member-function with `R` return value and `A...` arguments.
705 * @return anonymous function
706 * @see @ref function_ctor_member "function constructor for member function"
707 * @see @ref function_overview "function Overview"
708 * @see @ref function_usage "function Usage"
709 */
710 template<typename R, typename C0, typename C1, typename... A>
711 inline jau::function<R(A...)>
712 bind_member(C1 *base, R(C0::*mfunc)(A...)) noexcept {
713 return function<R(A...)>( std::make_shared<func::member_target_t<R, C0, C1, A...>>(base, mfunc),
714 sizeof(func::member_target_t<R, C0, C1, A...>) );
715 }
716
717 /**
718 * Bind given class instance and non-void member function to
719 * an anonymous function using func_member_targer_t.
720 *
721 * @tparam R function return type
722 * @tparam C class type holding the member-function and of this base pointer
723 * @tparam A function arguments
724 * @param base class instance `this` pointer
725 * @param mfunc member-function with `R` return value and `A...` arguments.
726 * @return anonymous function
727 * @see @ref function_ctor_member "function constructor for member function"
728 * @see @ref function_overview "function Overview"
729 * @see @ref function_usage "function Usage"
730 */
731 template<typename R, typename C, typename... A>
732 inline jau::function<R(A...)>
733 bind_member(C *base, R(C::*mfunc)(A...)) noexcept {
734 return function<R(A...)>( std::make_shared<func::member_target_t<R, C, C, A...>>(base, mfunc),
735 sizeof(func::member_target_t<R, C, C, A...>) );
736 }
737
738 /**
739 * Bind given class instance and void member function to
740 * an anonymous function using func_member_targer_t.
741 *
742 * @tparam C0 class type holding the member-function
743 * @tparam C1 class derived from C0 or C0 of this base-pointer used to invoke the member-function
744 * @tparam A function arguments
745 * @param base class instance `this` pointer
746 * @param mfunc member-function with `A...` arguments.
747 * @return anonymous function
748 * @see @ref function_ctor_member "function constructor for member function"
749 * @see @ref function_overview "function Overview"
750 * @see @ref function_usage "function Usage"
751 */
752 template<typename C0, typename C1, typename... A>
753 inline jau::function<void(A...)>
754 bind_member(C1 *base, void(C0::*mfunc)(A...)) noexcept {
755 return function<void(A...)>( std::make_shared<func::member_target_t<void, C0, C1, A...>>(base, mfunc),
756 sizeof(func::member_target_t<void, C0, C1, A...>) );
757 }
758
759 /**
760 * Bind given class instance and void member function to
761 * an anonymous function using func_member_targer_t.
762 *
763 * @tparam C class type holding the member-function and of this base pointer
764 * @tparam A function arguments
765 * @param base class instance `this` pointer
766 * @param mfunc member-function with `A...` arguments.
767 * @return anonymous function
768 * @see @ref function_ctor_member "function constructor for member function"
769 * @see @ref function_overview "function Overview"
770 * @see @ref function_usage "function Usage"
771 */
772 template<typename C, typename... A>
773 inline jau::function<void(A...)>
774 bind_member(C *base, void(C::*mfunc)(A...)) noexcept {
775 return function<void(A...)>( std::make_shared<func::member_target_t<void, C, C, A...>>(base, mfunc),
776 sizeof(func::member_target_t<void, C, C, A...>) );
777 }
778
779 /**
780 * Bind given non-void free-function to
781 * an anonymous function using func::free_target_t.
782 *
783 * @tparam R function return type
784 * @tparam A function arguments
785 * @param func free-function with `R` return value and `A...` arguments.
786 * @return anonymous function
787 * @see @ref function_ctor_free "function constructor for free function"
788 * @see @ref function_overview "function Overview"
789 * @see @ref function_usage "function Usage"
790 */
791 template<typename R, typename... A>
792 inline jau::function<R(A...)>
793 bind_free(R(*func)(A...)) noexcept {
794 return function<R(A...)>( std::make_shared<func::free_target_t<R, A...>>(func),
795 sizeof(func::free_target_t<R, A...>) );
796 }
797
798 /**
799 * Bind given void free-function to
800 * an anonymous function using func::free_target_t.
801 *
802 * @tparam A function arguments
803 * @param func free-function with `A...` arguments.
804 * @return anonymous function
805 * @see @ref function_ctor_free "function constructor for free function"
806 * @see @ref function_overview "function Overview"
807 * @see @ref function_usage "function Usage"
808 */
809 template<typename... A>
810 inline jau::function<void(A...)>
811 bind_free(void(*func)(A...)) noexcept {
812 return function<void(A...)>( std::make_shared<func::free_target_t<void, A...>>(func),
813 sizeof(func::free_target_t<void, A...>) );
814 }
815
816#if 0
817 // Lacks proper template type deduction, sadly
818
819 /**
820 * Bind given capturing non-void returning lambda by copying the it to
821 * an anonymous function using func::lambda_target_t.
822 *
823 * @tparam R function return type
824 * @tparam L typename holding the lambda closure
825 * @tparam A function arguments
826 * @param func the lambda reference
827 * @return anonymous function
828 * @see @ref function_ctor_lambda "function constructor for lambda"
829 * @see @ref function_overview "function Overview"
830 * @see @ref function_usage "function Usage"
831 */
832 template<typename R, typename L, typename... A>
833 inline jau::function<R(A...)>
834 bind_lambda(L func) noexcept {
835 return function<R(A...)>( std::make_shared<func::lambda_target_t<R, L, A...>>(func),
836 sizeof(func::lambda_target_t<R, L, A...>) );
837 }
838
839 /**
840 * Bind given capturing void returning lambda by copying the it to
841 * an anonymous function using func::lambda_target_t.
842 *
843 * @tparam L typename holding the lambda closure
844 * @tparam A function arguments
845 * @param func the lambda reference
846 * @return anonymous function
847 * @see @ref function_ctor_lambda "function constructor for lambda"
848 * @see @ref function_overview "function Overview"
849 * @see @ref function_usage "function Usage"
850 */
851 template<typename L, typename... A>
852 inline jau::function<void(A...)>
853 bind_lambda(L func) noexcept {
854 return function<void(A...)>( std::make_shared<func::lambda_target_t<void, L, A...>>(func),
855 sizeof(func::lambda_target_t<void, L, A...>) );
856 }
857#endif
858
859 /**
860 * Bind given data by copying the captured value and the given non-void function to
861 * an anonymous function using func::capval_target_t.
862 *
863 * `const I& data` will be copied into func::capval_target_t and hence captured by copy.
864 *
865 * The function invocation will have the reference of the copied data being passed to the target function for efficiency.
866 *
867 * @tparam R function return type
868 * @tparam I typename holding the captured data used by the function
869 * @tparam A function arguments
870 * @param data data type instance holding the captured data
871 * @param func function with `R` return value and `A...` arguments.
872 * @return anonymous function
873 * @see @ref function_ctor_capval_copy "function constructor for copying capturing value"
874 * @see @ref function_overview "function Overview"
875 * @see @ref function_usage "function Usage"
876 */
877 template<typename R, typename I, typename... A>
878 inline jau::function<R(A...)>
879 bind_capval(const I& data, R(*func)(I&, A...)) noexcept {
880 return function<R(A...)>( std::make_shared<func::capval_target_t<R, I, A...>>(data, func),
881 sizeof(func::capval_target_t<R, I, A...>) );
882 }
883
884 /**
885 * Bind given data by copying the captured value and the given void function to
886 * an anonymous function using func::capval_target_t.
887 *
888 * `const I& data` will be copied into func::capval_target_t and hence captured by copy.
889 *
890 * The function invocation will have the reference of the copied data being passed to the target function for efficiency.
891 *
892 * @tparam I typename holding the captured data used by the function
893 * @tparam A function arguments
894 * @param data data type instance holding the captured data
895 * @param func function with `A...` arguments.
896 * @return anonymous function
897 * @see @ref function_ctor_capval_copy "function constructor for copying capturing value"
898 * @see @ref function_overview "function Overview"
899 * @see @ref function_usage "function Usage"
900 */
901 template<typename I, typename... A>
902 inline jau::function<void(A...)>
903 bind_capval(const I& data, void(*func)(I&, A...)) noexcept {
904 return function<void(A...)>( std::make_shared<func::capval_target_t<void, I, A...>>(data, func),
905 sizeof(func::capval_target_t<void, I, A...>) );
906 }
907
908 /**
909 * Bind given data by moving the captured value and copying the given non-void function to
910 * an anonymous function using func::capval_target_t.
911 *
912 * `I&& data` will be moved into func::capval_target_t.
913 *
914 * The function invocation will have the reference of the moved data being passed to the target function for efficiency.
915 *
916 * @tparam R function return type
917 * @tparam I typename holding the captured data used by the function
918 * @tparam A function arguments
919 * @param data data type instance holding the captured data
920 * @param func function with `R` return value and `A...` arguments.
921 * @return anonymous function
922 * @see @ref function_ctor_capval_move "function constructor for moving capturing value"
923 * @see @ref function_overview "function Overview"
924 * @see @ref function_usage "function Usage"
925 */
926 template<typename R, typename I, typename... A>
927 inline jau::function<R(A...)>
928 bind_capval(I&& data, R(*func)(I&, A...)) noexcept {
929 return function<R(A...)>( std::make_shared<func::capval_target_t<R, I, A...>>(std::move(data), func),
930 sizeof(func::capval_target_t<R, I, A...>) );
931 }
932
933 /**
934 * Bind given data by moving the captured value and copying the given void function to
935 * an anonymous function using func::capval_target_t.
936 *
937 * `I&& data` will be moved into func::capval_target_t.
938 *
939 * The function invocation will have the reference of the moved data being passed to the target function for efficiency.
940 *
941 * @tparam I typename holding the captured data used by the function
942 * @tparam A function arguments
943 * @param data data type instance holding the captured data
944 * @param func function with `A...` arguments.
945 * @return anonymous function
946 * @see @ref function_ctor_capval_move "function constructor for moving capturing value"
947 * @see @ref function_overview "function Overview"
948 * @see @ref function_usage "function Usage"
949 */
950 template<typename I, typename... A>
951 inline jau::function<void(A...)>
952 bind_capval(I&& data, void(*func)(I&, A...)) noexcept {
953 return function<void(A...)>( std::make_shared<func::capval_target_t<void, I, A...>>(std::move(data), func),
954 sizeof(func::capval_target_t<void, I, A...>) );
955 }
956
957 /**
958 * Bind given data by passing the captured reference (pointer) to the value and non-void function to
959 * an anonymous function using func::capref_target_t.
960 *
961 * The function invocation will have the reference of the data being passed to the target function.
962 *
963 * @tparam R function return type
964 * @tparam I typename holding the captured data used by the function
965 * @tparam A function arguments
966 * @param data_ptr data type reference to instance holding the captured data
967 * @param func function with `R` return value and `A...` arguments.
968 * @return anonymous function
969 * @see @ref function_ctor_capref "function constructor for capturing reference"
970 * @see @ref function_overview "function Overview"
971 * @see @ref function_usage "function Usage"
972 */
973 template<typename R, typename I, typename... A>
974 inline jau::function<R(A...)>
975 bind_capref(I* data_ptr, R(*func)(I*, A...)) noexcept {
976 return function<R(A...)>( std::make_shared<func::capref_target_t<R, I, A...>>(data_ptr, func),
977 sizeof(func::capref_target_t<R, I, A...>) );
978 }
979
980 /**
981 * Bind given data by passing the captured reference (pointer) to the value and void function to
982 * an anonymous function using func::capref_target_t.
983 *
984 * The function invocation will have the reference of the data being passed to the target function.
985 *
986 * @tparam I typename holding the captured data used by the function
987 * @tparam A function arguments
988 * @param data_ptr data type reference to instance holding the captured data
989 * @param func function with `A...` arguments.
990 * @return anonymous function
991 * @see @ref function_ctor_capref "function constructor for capturing reference"
992 * @see @ref function_overview "function Overview"
993 * @see @ref function_usage "function Usage"
994 */
995 template<typename I, typename... A>
996 inline jau::function<void(A...)>
997 bind_capref(I* data_ptr, void(*func)(I*, A...)) noexcept {
998 return function<void(A...)>( std::make_shared<func::capref_target_t<void, I, A...>>(data_ptr, func),
999 sizeof(func::capref_target_t<void, I, A...>) );
1000 }
1001
1002 /**
1003 * Bind given non-void std::function to
1004 * an anonymous function using func::std_target_t.
1005 *
1006 * Notable, instance is holding the given unique uint64_t identifier
1007 * to allow implementing the equality operator w/o RTTI, not supported by std::function.
1008 *
1009 * @tparam R function return type
1010 * @tparam A function arguments
1011 * @param func free-function with `R` return value and `A...` arguments.
1012 * @return anonymous function
1013 * @see @ref function_ctor_std "function constructor for std::function"
1014 * @see @ref function_overview "function Overview"
1015 * @see @ref function_usage "function Usage"
1016 */
1017 template<typename R, typename... A>
1018 inline jau::function<R(A...)>
1019 bind_std(uint64_t id, std::function<R(A...)> func) noexcept {
1020 return function<R(A...)>( std::make_shared<func::std_target_t<R, A...>>(id, func),
1021 sizeof(func::std_target_t<R, A...>) );
1022 }
1023
1024 /**
1025 * Bind given void std::function to
1026 * an anonymous function using func::std_target_t.
1027 *
1028 * Notable, instance is holding the given unique uint64_t identifier
1029 * to allow implementing the equality operator w/o RTTI, not supported by std::function.
1030 *
1031 * @tparam A function arguments
1032 * @param func free-function with `A...` arguments.
1033 * @return anonymous function
1034 * @see @ref function_ctor_std "function constructor for std::function"
1035 * @see @ref function_overview "function Overview"
1036 * @see @ref function_usage "function Usage"
1037 */
1038 template<typename... A>
1039 inline jau::function<void(A...)>
1040 bind_std(uint64_t id, std::function<void(A...)> func) noexcept {
1041 return function<void(A...)>( std::make_shared<func::std_target_t<void, A...>>(id, func),
1042 sizeof(func::std_target_t<void, A...>) );
1043 }
1044
1045} // namespace jau
1046
1047/** \example test_functional01.cpp
1048 * This C++ unit test validates the jau::function<R(A...)> and all its jau::func::target_t specializations.
1049 */
1050
1051/** \example test_functional_perf.hpp
1052 * This C++ unit test benchmarks the jau::function<R(A...)> and all its jau::func::target_t specializations.
1053 */
1054
1055#endif /* JAU_FUNCTIONAL_HPP_ */
func::capref_target_t implementation for functions using a reference to a captured value,...
R operator()(A... args) override
bool operator==(const target_t< R, A... > &rhs) const noexcept override
capref_target_t(I *_data_ptr, R(*_function)(I *, A...)) noexcept
func::capval_target_t implementation for functions using a copy of a captured value,...
capval_target_t(const I &_data, R(*_function)(I &, A...)) noexcept
Utilizes copy-ctor from 'const I& _data'.
bool operator==(const target_t< R, A... > &rhs) const noexcept override
capval_target_t(I &&_data, R(*_function)(I &, A...)) noexcept
Utilizes move-ctor from moved 'I&& _data'.
R operator()(A... args) override
func::free_target_t implementation for free functions, identifiable as func::target_type::free via ja...
free_target_t(R(*_function)(A...)) noexcept
bool operator==(const target_t< R, A... > &rhs) const noexcept override
R operator()(A... args) override
func::lambda_target_t implementation for lambda closures, identifiable as func::target_type::lambda v...
R operator()(A... args) override
lambda_target_t(L function_) noexcept
bool operator==(const target_t< R, A... > &rhs) const noexcept override
func::member_target_t implementation for class member functions, identifiable as func::target_type::m...
R operator()(A... args) override
member_target_t(C1 *_base, R(C0::*_member)(A...), std::enable_if_t< std::is_base_of_v< C0, C1 >, bool >=true) noexcept
Construct a target_t<R, A...> instance from given this base-pointer and member-function.
bool operator==(const target_t< R, A... > &rhs) const noexcept override
func::null_target_t implementation for no function.
R operator()(A...) override
bool operator==(const target_t< R, A... > &rhs) const noexcept override
func::std_target_t implementation for std::function instances, identifiable as func::target_type::std...
R operator()(A... args) override
std_target_t(uint64_t _id, std::function< R(A...)> _function) noexcept
bool operator==(const target_t< R, A... > &rhs) const noexcept override
std_target_t(uint64_t _id) noexcept
func::target_t pure-virtual interface for jau::function.
target_t & operator=(const target_t &o) noexcept=default
target_t(const target_t &o) noexcept=default
target_t(target_type ttype_) noexcept
virtual R operator()(A... args)=0
target_t(target_t &&o) noexcept=default
target_t & operator=(target_t &&o) noexcept=default
virtual ~target_t() noexcept
virtual bool operator==(const target_t< R, A... > &rhs) const noexcept=0
constexpr target_type type() const noexcept
Return the func::target_type of this invocation function wrapper.
func::target_t< R, A... > target_type
The target function type, i.e.
function(C1 *base, R(C0::*mfunc)(A...)) noexcept
Member function constructor.
function & operator=(function &&o) noexcept=default
constexpr bool operator!=(const function< R(A...)> &rhs) const noexcept
constexpr size_t target_size() const noexcept
Returns the size of the target type.
constexpr func::target_type type() const noexcept
Return the jau::func::type of this instance.
function(L func) noexcept
Lambda function constructor.
std::string toString() const
constexpr bool operator==(const function< R(A...)> &rhs) const noexcept
function(uint64_t id, std::function< R(A...)> func) noexcept
std::function constructor
function(I &&data, R(*func)(I &, A...)) noexcept
Capture by value (move) function constructor.
function(const I &data, R(*func)(I &, A...)) noexcept
Capture by value (copy) function constructor.
function(R(*func)(A...)) noexcept
Free function constructor.
constexpr bool is_null() const noexcept
Returns true if this instance does not hold a callable target function, i.e.
function() noexcept
Null function constructor.
function(std::shared_ptr< target_type > _funcPtr, size_t asize_) noexcept
target_type constructor
R result_type
The target function return type R.
function & operator=(const function &o) noexcept=default
constexpr R operator()(A... args) const
function(function &&o) noexcept=default
jau::type_info signature() const noexcept
Returns signature of this function prototype R(A...) w/o underlying target function details.
function(const function &o) noexcept=default
function(I *data_ptr, R(*func)(I *, A...)) noexcept
Capture by reference function constructor.
function(std::nullptr_t) noexcept
Null function constructor.
constexpr R operator()(A... args)
Class template jau::function is a general-purpose static-polymorphic function wrapper.
Generic type information using either Runtime type information (RTTI) or Compile time type informatio...
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
jau::type_info make_ctti(bool identity_instance=false) noexcept
Constructs a jau::type_info instance based on given type T using template Compile Time Type Informati...
jau::function< R(A...)> bind_member(C1 *base, R(C0::*mfunc)(A...)) noexcept
Bind given class instance and non-void member function to an anonymous function using func_member_tar...
jau::function< R(A...)> bind_free(R(*func)(A...)) noexcept
Bind given non-void free-function to an anonymous function using func::free_target_t.
jau::function< R(A...)> bind_std(uint64_t id, std::function< R(A...)> func) noexcept
Bind given non-void std::function to an anonymous function using func::std_target_t.
target_type
func::target_type identifier for the target function delegate_t<R, A...> object, exposed by jau::func...
jau::function< R(A...)> bind_capval(const I &data, R(*func)(I &, A...)) noexcept
Bind given data by copying the captured value and the given non-void function to an anonymous functio...
jau::function< R(A...)> bind_capref(I *data_ptr, R(*func)(I *, A...)) noexcept
Bind given data by passing the captured reference (pointer) to the value and non-void function to an ...
constexpr uint32_t number(const func::target_type rhs) noexcept
@ null
Denotes a func::null_target_t.
@ lambda
Denotes a func::lambda_target_t.
@ capval
Denotes a func::capval_target_t.
@ capref
Denotes a func::capref_target_t.
@ member
Denotes a func::member_target_t.
@ free
Denotes a func::free_target_t.
@ std
Denotes a func::std_target_t.
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition backtrace.hpp:32
bool operator==(const callocator< T1 > &lhs, const callocator< T2 > &rhs) noexcept
bool operator!=(const callocator< T1 > &lhs, const callocator< T2 > &rhs) noexcept
STL namespace.