aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2022-09-19 05:51:22 +0200
committerSven Gothel <[email protected]>2022-09-19 05:51:22 +0200
commit647006203382112f9a625172e45a578c9c1e9aa8 (patch)
treeb8bbb278ba3237de3be9f95e5430ed18b96395d4
parent6e0e58de8f316d1600e01eded6ac3dcba13fc407 (diff)
Bump CHANGES.md, removed now obsolete test/functional1.hppv0.16.3
-rw-r--r--CHANGES.md3
-rw-r--r--test/functional1.hpp1169
2 files changed, 3 insertions, 1169 deletions
diff --git a/CHANGES.md b/CHANGES.md
index 388eecb..4628857 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -8,6 +8,9 @@
* First stable release (TODO)
+**0.16.3**
+* functional: Add general lambda support, revise API doc, have native target function size accessible
+
**0.16.2**
* Fix `jau::service_runner::start()`: Case `set_shall_stop()` occurs fast by worker callback -> infinite loop.
* `jau::function<R(A...)>`
diff --git a/test/functional1.hpp b/test/functional1.hpp
deleted file mode 100644
index 201150f..0000000
--- a/test/functional1.hpp
+++ /dev/null
@@ -1,1169 +0,0 @@
-/*
- * Author: Sven Gothel <[email protected]>
- * Copyright (c) 2020-2022 Gothel Software e.K.
- * Copyright (c) 2020 ZAFENA AB
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef JAU_FUNCTIONAL_HPP_
-#define JAU_FUNCTIONAL_HPP_
-
-#include <cstring>
-#include <string>
-#include <memory>
-#include <cstdint>
-#include <vector>
-#include <functional>
-
-#include <jau/basic_types.hpp>
-
-namespace jau {
-
- /** @defgroup FunctionWrap Function Wrapper
- * Supporting general-purpose polymorphic function wrapper via jau::function<R(A...)>.
- *
- * @anchor function_overview
- * ### Function Overview
- * Similar to std::function, [jau::function](@ref function_def) stores any callable target function
- * described by its return type `R` and arguments `A...` from any source,
- * e.g. free functions, member functions, etc.
- *
- * [jau::function](@ref function_def) supports equality operations for all func::target_t source types, allowing to manage container of [jau::function](@ref function_def)s.
- * This property distinguishes itself from std::function.
- *
- * Provided bind methods, see below, produce specific [jau::function](@ref function_def) instances,
- * where std::bind() is unspecific about the returned function type.
- *
- * Implementation utilizes a fast path target function [delegate](@ref delegate_class), see [func::target_t<R(A...)>::delegate_t:invoke()](@ref delegate_invoke).
- *
- * Instances of [jau::function](@ref function_def) can store, copy, and invoke any of its callable targets
- * - free functions including non-capturing lambda
- * - bind_free()
- * - constructor [jau::function<R(A...)>::function(R(*func)(A...))](@ref function_ctor_free)
- * - member functions
- * - bind_member()
- * - constructor [`function(C *base, R(C::*mfunc)(A...))`](@ref function_ctor_member)
- * - lambda alike functions using a captured data type by reference
- * - bind_capref()
- * - constructor [function(I* data_ptr, R(*func)(I*, A...), bool dataIsIdentity=true)](@ref function_ctor_capref)
- * - lambda alike functions using a captured data type by value
- * - bind_capval()
- * - constructor copy [function(const I& data, R(*func)(I&, A...), bool dataIsIdentity=true)](@ref function_ctor_capval_copy)
- * - constructor move [function(I&& data, R(*func)(I&, A...), bool dataIsIdentity=true)](@ref function_ctor_capval_move)
- * - std::function
- * - bind_std()
- * - constructor [function(uint64_t id, std::function<R(A...)> func)](@ref function_ctor_std)
- *
- * If a [jau::function](@ref function_def) contains no target, see jau::function<R(A...)>::is_null(), it is empty.
- * Invoking the target of an empty [jau::function](@ref function_def) has not operation nor side effects.
- *
- * [jau::function](@ref function_def) satisfies the requirements of CopyConstructible and CopyAssignable.
- *
- * #### C++11 Capturing Lambda Restrictions
- * A capturing lambda in C++11 produces decoration code accessing the captured elements,<br />
- * i.e. an anonymous helper class.<br />
- * Due to this fact, the return type is an undefined lambda specific<br/>
- * and hence we can't use it to feed the func::target_t into function requiring a well specified type.
- *
- * <pre>
- template<typename R, typename C, typename... A>
- inline function<R(A...)>
- bind_member(C *base, R(C::*mfunc)(A...)) {
- return ClassFunction<R, A...>(
- (void*)base,
- (void*)(*((void**)&mfunc)),
- [&](A... args)->R{ (base->*mfunc)(args...); });
- ^
- | Capturing lambda function-pointer are undefined!
- }
- </pre>
- *
- * A workaround is to use the provided func::capref_target_t and bind_capref().
- *
- * @anchor function_usage
- * #### Function Usage
- *
- * A detailed API usage is covered within [test_functional01.cpp](test_functional01_8cpp-example.html), see function `test00_usage()`.
- *
- * Let's assume we like to bind to the following
- * function prototype `bool func(int)`, which results to `jau::function<bool(int)>`:
- *
- * - Free function and non-capturing lambda via constructor and jau::bind_free()
- * - Prologue
- * ```
- * typedef bool(*cfunc)(int); // help template type deduction
- *
- * bool my_func(int v) { return 0 == v; }
- *
- * struct MyClass {
- * static bool func(int v) { return 0 == v; }
- * };
- * ```
- *
- * - Constructor [function(R(*func)(A...))](@ref function_ctor_free)
- * ```
- * jau::function<bool(int)> func0 = (cfunc) ( [](int v) -> bool {
- * return 0 == v;
- * } );
- *
- * jau::function<bool(int)> func1 = my_func;
- *
- * jau::function<bool(int)> func0 = &MyClass:func;
- * ```
- *
- * - Bind `jau::function<R(A...)> jau::bind_free(R(*func)(A...))`
- * ```
- * jau::function<bool(int)> func0 = jau::bind_free(&MyClass:func);
- *
- * jau::function<bool(int)> func1 = jau::bind_free(my_func);
- * ```
- *
- * - Class member functions via constructor and jau::bind_member()
- * - Prologue
- * ```
- * struct MyClass {
- * bool m_func(int v) { return 0 == v; }
- * };
- * MyClass i1;
- * ```
- *
- * - Constructor [function(C *base, R(C::*mfunc)(A...))](@ref function_ctor_member)
- * ```
- * jau::function<bool(int)> func(&i1, &MyClass::m_func);
- * ```
- *
- * - Bind `jau::function<R(A...)> jau::bind_member(C *base, R(C::*mfunc)(A...))`
- * ```
- * jau::function<bool(int)> func = jau::bind_member(&i1, &MyClass::m_func);
- * ```
- *
- * - Capture by reference to value via constructor and jau::bind_capref()
- * - Prologue
- * ```
- * struct big_data {
- * int sum;
- * };
- * big_data data { 0 };
- *
- * typedef bool(*cfunc)(big_data*, int); // help template type deduction
- * ```
- *
- * - Constructor [function(I* data_ptr, R(*func)(I*, A...), bool dataIsIdentity=true)](@ref function_ctor_capref)
- * ```
- * function<int(int)> func(&data,
- * (cfunc) ( [](big_data* data, int v) -> bool {
- * stats_ptr->sum += v;
- * return 0 == v;
- * } ) );
- * ```
- *
- * - Bind `jau::function<R(A...)> jau::bind_capref(I* data_ptr, R(*func)(I*, A...), bool dataIsIdentity)`
- * ```
- * jau::function<bool(int)> func = jau::bind_capref(&data,
- * (cfunc) ( [](big_data* data, int v) -> bool {
- * stats_ptr->sum += v;
- * return 0 == v;
- * } ) );
- * ```
- *
- * - Capture by copy of value via constructor and jau::bind_capval()
- * - Constructor copy [function(const I& data, R(*func)(I&, A...), bool dataIsIdentity=true)](@ref function_ctor_capval_copy)
- * - Constructor move [function(I&& data, R(*func)(I&, A...), bool dataIsIdentity=true)](@ref function_ctor_capval_move)
- * - Bind copy `jau::function<R(A...)> jau::bind_capval(const I& data, R(*func)(I&, A...), bool dataIsIdentity)`
- * - Bind move `jau::function<R(A...)> jau::bind_capval(I&& data, R(*func)(I&, A...), bool dataIsIdentity)` <br />
- * See example of *Capture by reference to value* above.
- *
- * - std::function function via constructor and jau::bind_std()
- * - Prologue
- * ```
- * std::function<bool(int)> func_stdlambda = [](int i)->bool {
- * return 0 == i;
- * };
- * ```
- *
- * - Constructor [function(uint64_t id, std::function<R(A...)> func)](@ref function_ctor_std)
- * ```
- * jau::function<bool(int)> func(100, func_stdlambda);
- * ```
- *
- * - Bind `function<R(A...)> jau::bind_std(uint64_t id, std::function<R(A...)> func)`
- * ```
- * jau::function<bool(int)> func = jau::bind_std(100, func_stdlambda);
- * ```
- * @{
- */
-
- namespace func {
-
- /** \addtogroup FunctionWrap
- *
- * @{
- */
-
- /**
- * func::target_type identifier for specializations of func::target_t
- * used by jau::function<R(A...)>::type().
- *
- * @see @ref function_overview "Function Overview" etc.
- */
- enum class target_type : int {
- /** Denotes a func::null_target_t */
- null = 0,
- /** Denotes a func::member_target_t */
- member = 1,
- /** Denotes a func::free_target_t */
- free = 2,
- /** Denotes a func::capval_target_t */
- capval = 3,
- /** Denotes a func::capref_target_t */
- capref = 4,
- /** Denotes a func::std_target_t */
- std = 5
- };
- constexpr int number(const target_type rhs) noexcept {
- return static_cast<int>(rhs);
- }
-
- /**
- * func::target_t pure-virtual interface for [jau::function](@ref function_def).
- *
- * Implementation utilizes a fast path target function [delegate](@ref delegate_class), see [func::target_t<R(A...)>::delegate_t:invoke()](@ref delegate_invoke).
- *
- * @tparam R function return type
- * @tparam A function arguments
- * @see @ref function_overview "Function Overview" etc.
- */
- template<typename R, typename... A>
- class target_t {
- public:
- typedef R(*invocation_t)(void* base, A... args);
-
- /**
- * @anchor delegate_class
- * Delegated target function details from specialization, allowing a fast path target function invocation, see [invoke()](@ref delegate_invoke).
- */
- class delegate_t final {
- private:
- /** Delegated specialization base pointer. */
- void* base;
- /** Delegated specialization callback. */
- invocation_t cb;
-
- public:
- delegate_t(void* base_, invocation_t cb_) noexcept
- : base(base_), cb(cb_) {}
-
- /**
- * \brief Delegated fast path target function invocation.
- *
- * @anchor delegate_invoke Fast path target function invocation using delegated artifacts
- * from the specialized instance allowing to
- * - bypass the virtual function table
- * - hence allowing constexpr inline here and at function<R(A...)> caller
- *
- * @param args target function arguments
- * @return target function result
- */
- constexpr R invoke(A... args) {
- return cb(base, args...);
- }
- };
-
- private:
- /** Delegated details from specialization. */
- delegate_t ddetail;
-
- protected:
- target_t(delegate_t ddetail_) noexcept
- : ddetail(ddetail_) {}
-
- public:
- virtual ~target_t() noexcept {}
-
- target_t(const target_t &o) noexcept = default;
- target_t(target_t &&o) noexcept = default;
- target_t& operator=(const target_t &o) noexcept = default;
- target_t& operator=(target_t &&o) noexcept = default;
-
- /** Return the func::target_type of this invocation function wrapper */
- virtual target_type type() const noexcept = 0;
-
- /** Returns if this this invocation function wrapper's is of jau::func::target_type::null */
- virtual bool is_null() const noexcept = 0;
-
- virtual target_t<R, A...> * clone() const noexcept = 0;
-
- /** Return pointer to delegated details from specialization. */
- constexpr delegate_t* delegate() noexcept { return &ddetail; }
-
- virtual bool operator==(const target_t<R, A...>& rhs) const noexcept = 0;
-
- virtual bool operator!=(const target_t<R, A...>& rhs) const noexcept = 0;
-
- virtual std::string toString() const = 0;
- };
-
- /**
- * func::null_target_t implementation for no function.
- * identifiable as jau::func::target_type::null via jau::function<R(A...)>::type().
- *
- * This special type is used for an empty [jau::function](@ref function_def) instance w/o holding a function,
- * e.g. when created with the default constructor.
- *
- * @tparam R function return type
- * @tparam A function arguments
- * @see @ref function_overview "Function Overview" etc.
- */
- template<typename R, typename... A>
- class null_target_t final : public target_t<R, A...> {
- private:
- typedef typename target_t<R, A...>::delegate_t delegate_t;
-
- constexpr static R invoke_impl(void* base, A... args) {
- (void)base;
- (void)(... , args);
- return R();
- }
-
- public:
- null_target_t() noexcept
- : target_t<R, A...>( delegate_t(static_cast<void*>(this), invoke_impl) )
- { }
-
- target_type type() const noexcept override { return target_type::null; }
- bool is_null() const noexcept override { return true; }
-
- target_t<R, A...> * clone() const noexcept override { return new null_target_t(); }
-
- bool operator==(const target_t<R, A...>& rhs) const noexcept override
- {
- return type() == rhs.type();
- }
-
- bool operator!=(const target_t<R, A...>& rhs) const noexcept override
- {
- return !( *this == rhs );
- }
-
- std::string toString() const override {
- return "null()";
- }
- };
-
- /**
- * func::member_target_t implementation for class member functions,
- * identifiable as func::target_type::member via jau::function<R(A...)>::type().
- *
- * @tparam R function return type
- * @tparam C class type holding the member-function
- * @tparam A function arguments
- * @see @ref function_overview "Function Overview" etc.
- */
- template<typename R, typename C, typename... A>
- class member_target_t final : public target_t<R, A...> {
- private:
- typedef typename target_t<R, A...>::delegate_t delegate_t;
-
- C* base;
- R(C::*member)(A...);
-
- constexpr static R invoke_impl(void* vbase, A... args) {
- member_target_t<R, C, A...>* base = static_cast<member_target_t<R, C, A...>*>(vbase);
- return ((base->base)->*(base->member))(args...);
- }
-
- public:
- member_target_t(C *_base, R(C::*_member)(A...)) noexcept
- : target_t<R, A...>( delegate_t(static_cast<void*>(this), invoke_impl) ),
- base(_base), member(_member) { }
-
- target_type type() const noexcept override { return target_type::member; }
- bool is_null() const noexcept override { return false; }
-
- target_t<R, A...> * clone() const noexcept override { return new member_target_t(*this); }
-
- bool operator==(const target_t<R, A...>& rhs) const noexcept override
- {
- if( &rhs == this ) {
- return true;
- }
- if( type() != rhs.type() ) {
- return false;
- }
- const member_target_t<R, C, A...> * prhs = static_cast<const member_target_t<R, C, A...>*>(&rhs);
- return base == prhs->base && member == prhs->member;
- }
-
- bool operator!=(const target_t<R, A...>& rhs) const noexcept override
- {
- return !( *this == rhs );
- }
-
- std::string toString() const override {
- // hack to convert member pointer to void *: '*((void**)&member)'
- return "member("+to_hexstring((uint64_t)base)+"->"+to_hexstring( *((void**)&member) ) + ")";
- }
- };
-
- /**
- * func::free_target_t implementation for free functions,
- * identifiable as func::target_type::free via jau::function<R(A...)>::type().
- *
- * @tparam R function return type
- * @tparam A function arguments
- * @see @ref function_overview "Function Overview" etc.
- */
- template<typename R, typename... A>
- class free_target_t final : public target_t<R, A...> {
- private:
- typedef typename target_t<R, A...>::delegate_t delegate_t;
-
- R(*function)(A...);
-
- constexpr static R invoke_impl(void* vbase, A... args) {
- free_target_t<R, A...>* base = static_cast<free_target_t<R, A...>*>(vbase);
- return (*base->function)(args...);
- }
-
- public:
- free_target_t(R(*_function)(A...)) noexcept
- : target_t<R, A...>( delegate_t(static_cast<void*>(this), invoke_impl) ),
- function(_function) { }
-
- target_type type() const noexcept override { return target_type::free; }
- bool is_null() const noexcept override { return false; }
-
- target_t<R, A...> * clone() const noexcept override { return new free_target_t(*this); }
-
- bool operator==(const target_t<R, A...>& rhs) const noexcept override
- {
- if( &rhs == this ) {
- return true;
- }
- if( type() != rhs.type() ) {
- return false;
- }
- const free_target_t<R, A...> * prhs = static_cast<const free_target_t<R, A...>*>(&rhs);
- return function == prhs->function;
- }
-
- bool operator!=(const target_t<R, A...>& rhs) const noexcept override
- {
- return !( *this == rhs );
- }
-
- std::string toString() const override {
- // hack to convert function pointer to void *: '*((void**)&function)'
- return "free("+to_hexstring( *( (void**) &function ) ) + ")";
- }
- };
-
- /**
- * func::capval_target_t implementation for functions using a copy of a captured value,
- * identifiable as func::target_type::capval via jau::function<R(A...)>::type().
- *
- * @tparam R function return type
- * @tparam I typename holding the captured data used by the function
- * @tparam A function arguments
- * @see @ref function_overview "Function Overview" etc.
- */
- template<typename R, typename I, typename... A>
- class capval_target_t final : public target_t<R, A...> {
- private:
- typedef typename target_t<R, A...>::delegate_t delegate_t;
-
- I data;
- R(*function)(I&, A...);
- bool dataIsIdentity;
-
- constexpr static R invoke_impl(void* vbase, A... args) {
- capval_target_t<R, I, A...>* base = static_cast<capval_target_t<R, I, A...>*>(vbase);
- return (*base->function)(base->data, args...);
- }
-
- public:
- /** Utilizes copy-ctor from 'const I& _data' */
- capval_target_t(const I& _data, R(*_function)(I&, A...), bool dataIsIdentity_) noexcept
- : target_t<R, A...>( delegate_t(static_cast<void*>(this), invoke_impl) ),
- data(_data), function(_function), dataIsIdentity(dataIsIdentity_) { }
-
- /** Utilizes move-ctor from moved 'I&& _data' */
- capval_target_t(I&& _data, R(*_function)(I&, A...), bool dataIsIdentity_) noexcept
- : target_t<R, A...>( delegate_t(static_cast<void*>(this), invoke_impl) ),
- data(std::move(_data)), function(_function), dataIsIdentity(dataIsIdentity_) { }
-
- target_type type() const noexcept override { return target_type::capval; }
- bool is_null() const noexcept override { return false; }
-
- target_t<R, A...> * clone() const noexcept override { return new capval_target_t(*this); }
-
- bool operator==(const target_t<R, A...>& rhs) const noexcept override
- {
- if( &rhs == this ) {
- return true;
- }
- if( type() != rhs.type() ) {
- return false;
- }
- const capval_target_t<R, I, A...> * prhs = static_cast<const capval_target_t<R, I, A...>*>(&rhs);
- return dataIsIdentity == prhs->dataIsIdentity && function == prhs->function && ( !dataIsIdentity || data == prhs->data );
- }
-
- bool operator!=(const target_t<R, A...>& rhs) const noexcept override
- {
- return !( *this == rhs );
- }
-
- std::string toString() const override {
- // hack to convert function pointer to void *: '*((void**)&function)'
- return "capval("+to_hexstring( *((void**)&function) ) + ")";
- }
- };
-
- /**
- * func::capref_target_t implementation for functions using a reference to a captured value,
- * identifiable as func::target_type::capref via jau::function<R(A...)>::type().
- *
- * @tparam R function return type
- * @tparam I typename holding the captured data used by the function
- * @tparam A function arguments
- * @see @ref function_overview "Function Overview" etc.
- */
- template<typename R, typename I, typename... A>
- class capref_target_t final : public target_t<R, A...> {
- private:
- typedef typename target_t<R, A...>::delegate_t delegate_t;
-
- I* data_ptr;
- R(*function)(I*, A...);
- bool dataIsIdentity;
-
- constexpr static R invoke_impl(void* vbase, A... args) {
- capref_target_t<R, I, A...>* base = static_cast<capref_target_t<R, I, A...>*>(vbase);
- return (*base->function)(base->data_ptr, args...);
- }
-
- public:
- capref_target_t(I* _data_ptr, R(*_function)(I*, A...), bool dataIsIdentity_) noexcept
- : target_t<R, A...>( delegate_t(static_cast<void*>(this), invoke_impl) ),
- data_ptr(_data_ptr), function(_function), dataIsIdentity(dataIsIdentity_) { }
-
- target_type type() const noexcept override { return target_type::capref; }
- bool is_null() const noexcept override { return false; }
-
- target_t<R, A...> * clone() const noexcept override { return new capref_target_t(*this); }
-
- bool operator==(const target_t<R, A...>& rhs) const noexcept override
- {
- if( &rhs == this ) {
- return true;
- }
- if( type() != rhs.type() ) {
- return false;
- }
- const capref_target_t<R, I, A...> * prhs = static_cast<const capref_target_t<R, I, A...>*>(&rhs);
- return dataIsIdentity == prhs->dataIsIdentity && function == prhs->function && ( !dataIsIdentity || data_ptr == prhs->data_ptr );
- }
-
- bool operator!=(const target_t<R, A...>& rhs) const noexcept override
- {
- return !( *this == rhs );
- }
-
- std::string toString() const override {
- // hack to convert function pointer to void *: '*((void**)&function)'
- return "capref("+to_hexstring( *((void**)&function) ) + ")";
- }
- };
-
- /**
- * func::std_target_t implementation for std::function instances,
- * identifiable as func::target_type::std via jau::function<R(A...)>::type().
- *
- * Notable, instance is holding a unique uint64_t identifier
- * to allow implementing the equality operator, not supported by std::function.
- *
- * @tparam R function return type
- * @tparam A function arguments
- * @see @ref function_overview "Function Overview" etc.
- */
- template<typename R, typename... A>
- class std_target_t : public target_t<R, A...> {
- private:
- typedef typename target_t<R, A...>::delegate_t delegate_t;
-
- uint64_t id;
- std::function<R(A...)> function;
-
- constexpr static R invoke_impl(void* vbase, A... args) {
- std_target_t<R, A...>* base = static_cast<std_target_t<R, A...>*>(vbase);
- return (base->function)(args...);
- }
-
- public:
- std_target_t(uint64_t _id, std::function<R(A...)> _function) noexcept
- : target_t<R, A...>( delegate_t(static_cast<void*>(this), invoke_impl) ),
- id(_id), function(_function) { }
-
- std_target_t(uint64_t _id) noexcept
- : target_t<R, A...>( delegate_t(static_cast<void*>(this), invoke_impl) ),
- id(_id), function() { }
-
- target_type type() const noexcept override { return target_type::std; }
- bool is_null() const noexcept override { return false; }
-
- target_t<R, A...> * clone() const noexcept override { return new std_target_t(*this); }
-
- bool operator==(const target_t<R, A...>& rhs) const noexcept override
- {
- if( &rhs == this ) {
- return true;
- }
- if( type() != rhs.type() ) {
- return false;
- }
- const std_target_t<R, A...> * prhs = static_cast<const std_target_t<R, A...>*>(&rhs);
- return id == prhs->id;
- }
-
- bool operator!=(const target_t<R, A...>& rhs) const noexcept override
- {
- return !( *this == rhs );
- }
-
- std::string toString() const override {
- return "std("+to_hexstring( id )+")";
- }
- };
-
- /**@}*/
-
- } /* namespace func */
-
- /**
- * [Function](@ref function_overview} class template [jau::function](@ref function_def) is a general-purpose polymorphic function wrapper.
- *
- * See @ref function_overview "Function Overview".
- *
- * This is the dummy template variant, allowing the void- and non-void return type target specializations.
- *
- * @see @ref function_def "Function template definition"
- */
- template<typename Signature>
- class function;
-
- /**
- * @anchor function_def
- * Class template [jau::function](@ref function_def) is a general-purpose polymorphic function wrapper.
- *
- * See @ref function_overview "Function Overview".
- *
- * @tparam R function return type
- * @tparam A function arguments
- * @see @ref function_overview "Function Overview" etc.
- * @see @ref function_usage "Function Usage"
- */
- template<typename R, typename... A>
- class function<R(A...)> {
- public:
- /** The target function type, i.e. func::target_t<R, A...> */
- typedef func::target_t<R, A...> target_type;
-
- private:
- std::shared_ptr<target_type> target_func;
- typename func::target_t<R, A...>::delegate_t* ddetail;
-
- public:
- /** The target function return type R */
- typedef R result_type;
-
- /**
- * \brief Null function constructor
- *
- * @anchor function_ctor_def
- * Constructs an instance with a null target function.
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- function() noexcept
- : target_func( std::make_shared<func::null_target_t<R, A...>>() ),
- ddetail( target_func->delegate() )
- { }
-
- /**
- * \brief Null function constructor
- *
- * @anchor function_ctor_nullptr
- * Constructs an instance with a null target function.
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- function(std::nullptr_t ) noexcept
- : target_func( std::make_shared<func::null_target_t<R, A...>>() ),
- ddetail( target_func->delegate() )
- { }
-
- /**
- * \brief target_type constructor
- *
- * @anchor function_ctor_target_type
- * Constructs an instance with the given shared target function pointer.
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- function(std::shared_ptr<target_type> _funcPtr) noexcept
- : target_func( _funcPtr ),
- ddetail( target_func->delegate() )
- { }
-
- /**
- * \brief Free function constructor
- *
- * @anchor function_ctor_free
- * Constructs an instance by taking a free target function, which may also be a non-capturing lambda.
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- function(R(*func)(A...)) noexcept
- : target_func( std::make_shared<func::free_target_t<R, A...>>(func) ),
- ddetail( target_func->delegate() )
- { }
-
- /**
- * \brief Member function constructor
- *
- * \anchor function_ctor_member
- * Constructs an instance by taking a member target function.
- * @tparam C typename holding the class type of the member function
- * @param base pointer to the class instance of the member function
- * @param mfunc member function of class
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename C>
- function(C *base, R(C::*mfunc)(A...)) noexcept
- : target_func( std::make_shared<func::member_target_t<R, C, A...>>(base, mfunc) ),
- ddetail( target_func->delegate() )
- { }
-
- /**
- * \brief Capture by value (copy) function constructor
- *
- * @anchor function_ctor_capval_copy
- * Constructs an instance by copying the captured value and the given non-void function to
- * an anonymous function using func::capval_target_t.
- *
- * `const I& data` will be copied into func::capval_target_t and hence captured by copy.
- *
- * The function invocation will have the reference of the copied data being passed to the target function for efficiency.
- *
- * @tparam I typename holding the captured data used by the function
- * @param data data type instance holding the captured data
- * @param func function with `R` return value and `A...` arguments.
- * @param dataIsIdentity if true (default), equality requires equal data. Otherwise equality only compares the function pointer.
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename I>
- function(const I& data, R(*func)(I&, A...), bool dataIsIdentity=true) noexcept
- : target_func( std::make_shared<func::capval_target_t<R, I, A...>>(data, func, dataIsIdentity) ),
- ddetail( target_func->delegate() )
- { }
-
- /**
- * \brief Capture by value (move) function constructor
- *
- * @anchor function_ctor_capval_move
- * Constructs an instance by moving the captured value and copying the given non-void function to
- * an anonymous function using func::capval_target_t.
- *
- * `I&& data` will be moved into func::capval_target_t.
- *
- * The function invocation will have the reference of the moved data being passed to the target function for efficiency.
- *
- * @tparam I typename holding the captured data used by the function
- * @param data data type instance holding the captured data
- * @param func function with `R` return value and `A...` arguments.
- * @param dataIsIdentity if true (default), equality requires equal data. Otherwise equality only compares the function pointer.
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename I>
- function(I&& data, R(*func)(I&, A...), bool dataIsIdentity=true) noexcept
- : target_func( std::make_shared<func::capval_target_t<R, I, A...>>(std::move(data), func, dataIsIdentity) ),
- ddetail( target_func->delegate() )
- { }
-
- /**
- * \brief Capture by reference function constructor
- *
- * @anchor function_ctor_capref
- * Constructs an instance by passing the captured reference (pointer) to the value and non-void function to
- * an anonymous function using func::capref_target_t.
- *
- * The function invocation will have the reference of the data being passed to the target function.
- *
- * @tparam I typename holding the captured data used by the function
- * @param data_ptr data type reference to instance holding the captured data
- * @param func function with `R` return value and `A...` arguments.
- * @param dataIsIdentity if true (default), equality requires same data_ptr. Otherwise equality only compares the function pointer.
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename I>
- function(I* data_ptr, R(*func)(I*, A...), bool dataIsIdentity=true) noexcept
- : target_func( std::make_shared<func::capref_target_t<R, I, A...>>(data_ptr, func, dataIsIdentity) ),
- ddetail( target_func->delegate() )
- { }
-
- /**
- * \brief std::function constructor
- *
- * @anchor function_ctor_std
- * Constructs an instance by copying the std::function to
- * an anonymous function using func::std_target_t.
- *
- * Notable, instance is holding the given unique uint64_t identifier
- * to allow implementing the equality operator w/o RTTI, not supported by std::function.
- *
- * @param func free-function with `R` return value and `A...` arguments.
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- function(uint64_t id, std::function<R(A...)> func) noexcept
- : target_func( std::make_shared<func::std_target_t<R, A...>>(id, func) ),
- ddetail( target_func->delegate() )
- { }
-
- function(const function &o) noexcept
- : target_func( o.target_func ),
- ddetail( target_func->delegate() )
- { }
-
- function(function &&o) noexcept
- : target_func( std::move( o.target_func ) ),
- ddetail( target_func->delegate() )
- { o.target_func = nullptr; }
-
- function& operator=(const function &o) noexcept
- {
- target_func = o.target_func;
- ddetail = target_func->delegate();
- return *this;
- }
-
- function& operator=(function &&o) noexcept
- {
- target_func = std::move(o.target_func);
- ddetail = target_func->delegate();
- o.target_func = nullptr;
- return *this;
- }
-
- bool operator==(const function<R(A...)>& rhs) const noexcept
- { return *target_func == *rhs.target_func; }
-
- bool operator!=(const function<R(A...)>& rhs) const noexcept
- { return *target_func != *rhs.target_func; }
-
- /** Return the jau::func::type of this instance */
- func::target_type type() const noexcept { return target_func->type(); }
-
- /** Returns true if this instance does not hold a callable target function, i.e. is of func::target_type::null. */
- bool is_null() const noexcept { return target_func->is_null(); }
-
- /** Returns true if this instance holds a callable target function, i.e. is not of func::target_type::null. */
- explicit operator bool() const noexcept { return !target_func->is_null(); }
-
- /** Returns the shared target function. */
- std::shared_ptr<target_type> target() noexcept { return target_func; }
-
- std::string toString() const {
- return "function["+target_func->toString()+"]";
- }
-
- constexpr R operator()(A... args) const {
- return ddetail->invoke(args...);
- }
- constexpr R operator()(A... args) {
- return ddetail->invoke(args...);
- }
- };
-
- /**
- * Bind given class instance and non-void member function to
- * an anonymous function using func_member_targer_t.
- *
- * @tparam R function return type
- * @tparam C class type holding the member-function
- * @tparam A function arguments
- * @param base class instance `this` pointer
- * @param mfunc member-function with `R` return value and `A...` arguments.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename R, typename C, typename... A>
- inline jau::function<R(A...)>
- bind_member(C *base, R(C::*mfunc)(A...)) noexcept {
- return function<R(A...)>( std::make_shared<func::member_target_t<R, C, A...>>(base, mfunc) );
- }
-
- /**
- * Bind given class instance and void member function to
- * an anonymous function using func_member_targer_t.
- *
- * @tparam C class type holding the member-function
- * @tparam A function arguments
- * @param base class instance `this` pointer
- * @param mfunc member-function with `A...` arguments.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename C, typename... A>
- inline jau::function<void(A...)>
- bind_member(C *base, void(C::*mfunc)(A...)) noexcept {
- return function<void(A...)>( std::make_shared<func::member_target_t<void, C, A...>>(base, mfunc) );
- }
-
- /**
- * Bind given non-void free-function to
- * an anonymous function using func::free_target_t.
- *
- * @tparam R function return type
- * @tparam A function arguments
- * @param func free-function with `R` return value and `A...` arguments.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename R, typename... A>
- inline jau::function<R(A...)>
- bind_free(R(*func)(A...)) noexcept {
- return function<R(A...)>( std::make_shared<func::free_target_t<R, A...>>(func) );
- }
-
- /**
- * Bind given void free-function to
- * an anonymous function using func::free_target_t.
- *
- * @tparam A function arguments
- * @param func free-function with `A...` arguments.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename... A>
- inline jau::function<void(A...)>
- bind_free(void(*func)(A...)) noexcept {
- return function<void(A...)>( std::make_shared<func::free_target_t<void, A...>>(func) );
- }
-
- /**
- * Bind given data by copying the captured value and the given non-void function to
- * an anonymous function using func::capval_target_t.
- *
- * `const I& data` will be copied into func::capval_target_t and hence captured by copy.
- *
- * The function invocation will have the reference of the copied data being passed to the target function for efficiency.
- *
- * @tparam R function return type
- * @tparam I typename holding the captured data used by the function
- * @tparam A function arguments
- * @param data data type instance holding the captured data
- * @param func function with `R` return value and `A...` arguments.
- * @param dataIsIdentity if true (default), equality requires equal data. Otherwise equality only compares the function pointer.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename R, typename I, typename... A>
- inline jau::function<R(A...)>
- bind_capval(const I& data, R(*func)(I&, A...), bool dataIsIdentity=true) noexcept {
- return function<R(A...)>( std::make_shared<func::capval_target_t<R, I, A...>>(data, func, dataIsIdentity) );
- }
-
- /**
- * Bind given data by copying the captured value and the given void function to
- * an anonymous function using func::capval_target_t.
- *
- * `const I& data` will be copied into func::capval_target_t and hence captured by copy.
- *
- * The function invocation will have the reference of the copied data being passed to the target function for efficiency.
- *
- * @tparam I typename holding the captured data used by the function
- * @tparam A function arguments
- * @param data data type instance holding the captured data
- * @param func function with `A...` arguments.
- * @param dataIsIdentity if true (default), equality requires equal data. Otherwise equality only compares the function pointer.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename I, typename... A>
- inline jau::function<void(A...)>
- bind_capval(const I& data, void(*func)(I&, A...), bool dataIsIdentity=true) noexcept {
- return function<void(A...)>( std::make_shared<func::capval_target_t<void, I, A...>>(data, func, dataIsIdentity) );
- }
-
- /**
- * Bind given data by moving the captured value and copying the given non-void function to
- * an anonymous function using func::capval_target_t.
- *
- * `I&& data` will be moved into func::capval_target_t.
- *
- * The function invocation will have the reference of the moved data being passed to the target function for efficiency.
- *
- * @tparam R function return type
- * @tparam I typename holding the captured data used by the function
- * @tparam A function arguments
- * @param data data type instance holding the captured data
- * @param func function with `R` return value and `A...` arguments.
- * @param dataIsIdentity if true (default), equality requires equal data. Otherwise equality only compares the function pointer.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename R, typename I, typename... A>
- inline jau::function<R(A...)>
- bind_capval(I&& data, R(*func)(I&, A...), bool dataIsIdentity=true) noexcept {
- return function<R(A...)>( std::make_shared<func::capval_target_t<R, I, A...>>(std::move(data), func, dataIsIdentity) );
- }
-
- /**
- * Bind given data by moving the captured value and copying the given void function to
- * an anonymous function using func::capval_target_t.
- *
- * `I&& data` will be moved into func::capval_target_t.
- *
- * The function invocation will have the reference of the moved data being passed to the target function for efficiency.
- *
- * @tparam I typename holding the captured data used by the function
- * @tparam A function arguments
- * @param data data type instance holding the captured data
- * @param func function with `A...` arguments.
- * @param dataIsIdentity if true (default), equality requires equal data. Otherwise equality only compares the function pointer.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename I, typename... A>
- inline jau::function<void(A...)>
- bind_capval(I&& data, void(*func)(I&, A...), bool dataIsIdentity=true) noexcept {
- return function<void(A...)>( std::make_shared<func::capval_target_t<void, I, A...>>(std::move(data), func, dataIsIdentity) );
- }
-
- /**
- * Bind given data by passing the captured reference (pointer) to the value and non-void function to
- * an anonymous function using func::capref_target_t.
- *
- * The function invocation will have the reference of the data being passed to the target function.
- *
- * @tparam R function return type
- * @tparam I typename holding the captured data used by the function
- * @tparam A function arguments
- * @param data_ptr data type reference to instance holding the captured data
- * @param func function with `R` return value and `A...` arguments.
- * @param dataIsIdentity if true (default), equality requires same data_ptr. Otherwise equality only compares the function pointer.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename R, typename I, typename... A>
- inline jau::function<R(A...)>
- bind_capref(I* data_ptr, R(*func)(I*, A...), bool dataIsIdentity=true) noexcept {
- return function<R(A...)>( std::make_shared<func::capref_target_t<R, I, A...>>(data_ptr, func, dataIsIdentity) );
- }
-
- /**
- * Bind given data by passing the captured reference (pointer) to the value and void function to
- * an anonymous function using func::capref_target_t.
- *
- * The function invocation will have the reference of the data being passed to the target function.
- *
- * @tparam I typename holding the captured data used by the function
- * @tparam A function arguments
- * @param data_ptr data type reference to instance holding the captured data
- * @param func function with `A...` arguments.
- * @param dataIsIdentity if true (default), equality requires same data_ptr. Otherwise equality only compares the function pointer.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename I, typename... A>
- inline jau::function<void(A...)>
- bind_capref(I* data_ptr, void(*func)(I*, A...), bool dataIsIdentity=true) noexcept {
- return function<void(A...)>( std::make_shared<func::capref_target_t<void, I, A...>>(data_ptr, func, dataIsIdentity) );
- }
-
- /**
- * Bind given non-void std::function to
- * an anonymous function using func::std_target_t.
- *
- * Notable, instance is holding the given unique uint64_t identifier
- * to allow implementing the equality operator w/o RTTI, not supported by std::function.
- *
- * @tparam R function return type
- * @tparam A function arguments
- * @param func free-function with `R` return value and `A...` arguments.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename R, typename... A>
- inline jau::function<R(A...)>
- bind_std(uint64_t id, std::function<R(A...)> func) noexcept {
- return function<R(A...)>( std::make_shared<func::std_target_t<R, A...>>(id, func) );
- }
-
- /**
- * Bind given void std::function to
- * an anonymous function using func::std_target_t.
- *
- * Notable, instance is holding the given unique uint64_t identifier
- * to allow implementing the equality operator w/o RTTI, not supported by std::function.
- *
- * @tparam A function arguments
- * @param func free-function with `A...` arguments.
- * @return anonymous function
- * @see @ref function_overview "function Overview" etc.
- * @see @ref function_usage "function Usage"
- */
- template<typename... A>
- inline jau::function<void(A...)>
- bind_std(uint64_t id, std::function<void(A...)> func) noexcept {
- return function<void(A...)>( std::make_shared<func::std_target_t<void, A...>>(id, func) );
- }
-
- /**@}*/
-
-} // namespace jau
-
-/** \example test_functional01.cpp
- * This C++ unit test validates the jau::function<R(A...)> and all its jau::func::target_t specializations.
- */
-
-/** \example test_functional_perf.hpp
- * This C++ unit test benchmarks the jau::function<R(A...)> and all its jau::func::target_t specializations.
- */
-
-#endif /* JAU_FUNCTIONAL_HPP_ */