#include <cassert>
#include <cinttypes>
#include <cstring>
#include <string>
 
#if !FUNCTIONAL_PROVIDED
    static std::string 
impl_name = 
"jau/functional.hpp";
 
#endif
 
#ifndef FUNCTIONAL_IMPL
  #define FUNCTIONAL_IMPL 1
#endif
 
#include <jau/test/catch2_ext.hpp>
 
 
  public:
    const int loops = 1000000;
 
 
        INFO(
"Test 00_usage: START: Implementation = functional "+std::to_string( 
FUNCTIONAL_IMPL ));
        fprintf(stderr, "Implementation: functional %d, is_rtti_available %d, limited_lambda_id %d\n",
        {
            
            volatile int i = 100;
 
            {
                    return i + a;
                };
                fprintf(stderr, "lambda.ref:    %s\n", fa0.toString().c_str());
            }
 
            {
                    return i + a;
                };
                fprintf(stderr, "lambda.copy:   %s\n", fa0.toString().c_str());
            }
        }
        {
            
                return a + 100;
            } ;
            fprintf(stderr, "lambda.plain:  %s\n", f_1.toString().c_str());
        }
#if ( FUNCTIONAL_IMPL == 1 || FUNCTIONAL_IMPL == 2 )
        {
            
                if( 0 == x ) {
                    return 1;
                } else {
                    return x * self(x-1);
                }
            } );
            fprintf(stderr, "ylambda.plain1 %s\n", f_1.toString().c_str());
        }
        {
            
                if( 0 == x ) {
                    return 1;
                } else {
                    return x * self(x-1);
                }
            } );
            fprintf(stderr, "ylambda.plain2 %s\n", f_1.toString().c_str());
        }
#endif
        {
            
            typedef void(*cfunc)();
                
            } );
            fprintf(stderr, "freeA.0        %s\n", fl_0.toString().c_str());
        }
        {
            
            jau::function<int(
int)> f2a_0(
this, &TestFunction01::func02a_member);
 
            fprintf(stderr, "member:        %s\n", f2a_0.toString().c_str());
        }
        {
            
            jau::function<void(
int&, 
int)> f2a_0(
this, &TestFunction01::func12a_member);
 
            fprintf(stderr, "member:        %s\n", f2a_0.toString().c_str());
        }
        {
            
            int offset100 = 100;
 
            typedef int(*cfunc)(int&, int); 
 
                    (cfunc) ( [](int& capture, int i)->int {
                        int res = i+10000+capture;
                        return res;
                    } ) );
            fprintf(stderr, "capval.small:  %s\n", f5_o100_1.toString().c_str());
        }
        {
            
            struct blob {
                int offset100 = 100;
                uint64_t lala0 = 0;
                uint64_t lala1 = 1;
                uint64_t lala2 = 2;
                uint64_t lala3 = 3;
 
                    return offset100 == rhs.offset100 &&
                           lala0 == rhs.lala0 &&
                           lala1 == rhs.lala1 &&
                           lala2 == rhs.lala2 &&
                           lala3 == rhs.lala3;
                }
                { return !( *this == rhs ); }
 
            };
            blob b0;
 
            typedef int(*cfunc)(blob&, int); 
 
                    (cfunc) ( [](blob& capture, int i)->int {
                        int res = i+10000+capture.offset100;
                        return res;
                    } ) );
            fprintf(stderr, "capval.big:    %s\n", f5_o100_1.toString().c_str());
        }
        {
            
            int offset100 = 100;
 
            typedef int(*cfunc)(int*, int); 
 
                    (cfunc) ( [](int* capture, int i)->int {
                        int res = i+10000+(*capture);
                        return res;;
                    } ) );
            fprintf(stderr, "capref:        %s\n", f7_o100_1.toString().c_str());
        }
        {
            
            std::function<int(int i)> func4a_stdlambda = [](int i)->int {
                int res = i+100;
                return res;;
            };
            fprintf(stderr, "std.lambda pl: %s\n", f.toString().c_str());
            fprintf(stderr, "  (net std.lambda):    sizeof %zu\n", sizeof(func4a_stdlambda));
        }
        {
            
            volatile int i = 100;
            std::function<int(int)> func4a_stdlambda = [&](int a) -> int {
                return i + a;
            };
 
            fprintf(stderr, "std.lambda cp: %s\n", f.toString().c_str());
            fprintf(stderr, "  (net std.lambda):    sizeof %zu\n", sizeof(func4a_stdlambda));
        }
    }
 
        INFO("Test 00_usage: START");
 
        
        {
            BENCHMARK("free_rawfunc") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + TestFunction01::Func03a_static(i);
                }
                return r;
            };
        }
 
        
        {
            native_func_t f = TestFunction01::Func03a_static;
 
            BENCHMARK("free_cfuncptr") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
 
        
        {
            std::function<int(int)> f = TestFunction01::Func03a_static;
 
            BENCHMARK("free_stdfunc") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
 
        
        {
 
            BENCHMARK("free_jaufunc") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
 
        
        {
            BENCHMARK("member_rawfunc") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + func02a_member(i);
                }
                return r;
            };
        }
 
        
        {
            using namespace std::placeholders;  
            auto f = std::bind(&TestFunction01::func02a_member, this, _1);
 
            BENCHMARK("member_stdbind_unspec") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
 
        
        {
 
            BENCHMARK("member_jaufunc") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
 
        
        {
            int offset100 = 100;
 
            int(*func5a_capture)(int&, int) = [](int& capture, int i)->int {
                int res = i+capture;
                return res;
            };
 
            BENCHMARK("capval_small_jaufunc") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
 
        {
            
            struct blob {
                int offset100 = 100;
                uint64_t lala0 = 0;
                uint64_t lala1 = 1;
                uint64_t lala2 = 2;
                uint64_t lala3 = 3;
 
                    return offset100 == rhs.offset100 &&
                           lala0 == rhs.lala0 &&
                           lala1 == rhs.lala1 &&
                           lala2 == rhs.lala2 &&
                           lala3 == rhs.lala3;
                }
                { return !( *this == rhs ); }
 
            };
            blob b0;
 
            typedef int(*cfunc)(blob&, int); 
 
                    (cfunc) ( [](blob& capture, int i)->int {
                        int res = i+10000+capture.offset100;
                        return res;
                    } ) );
 
            BENCHMARK("capval_big_jaufunc") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
 
        
        {
            int offset100 = 100;
 
            int(*func7a_capture)(int*, int) = [](int* capture, int i)->int {
                int res = i+*capture;
                return res;
            };
 
            BENCHMARK("capref_jaufunc") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
 
        
        {
            std::function<int(int i)> f = [](int i)->int {
                int res = i+100;
                return res;;
            };
 
            BENCHMARK("lambda_plain_std_function") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
 
        
        {
                return 100+ a;
            };
 
            BENCHMARK("lambda_plain_jaufunc") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
 
        
        {
            volatile int captured = 100;
 
            std::function<int(int)> f = [&](int a) -> int {
                return captured + a;
            };
 
            BENCHMARK("lambda_capt_std_function") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
 
        
        {
            volatile int captured = 100;
 
                return captured + a;
            };
 
            BENCHMARK("lambda_capt_jaufunc") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
        }
#if ( FUNCTIONAL_IMPL == 1 || FUNCTIONAL_IMPL == 2 )
        {
                (void)self; 
                return 100+x;
            } );
 
            BENCHMARK("ylambda_none_jaufunc") {
                volatile int r=0;
                for(
int i=0; i<
loops; ++i) {
 
                    r = r + f(i);
                }
                return r;
            };
 
        }
#endif
 
        REQUIRE( true == true );
 
        INFO("Test 00_usage: END");
    }
 
  private:
 
    typedef int(*native_func_t)(int);
    typedef std::function<int(int)> std_func_t;
 
    
    typedef int(*MyCFunc0)(int);
 
 
    int func02a_member(int i) {
        int res = i+100;
        return res;;
    }
    int func02b_member(int i) noexcept {
        int res = i+1000;
        return res;
    }
    static int Func03a_static(int i) {
        int res = i+100;
        return res;
    }
    static int Func03b_static(int i) noexcept {
        int res = i+1000;
        return res;
    }
 
    void func12a_member(int& r, const int i) {
        r = i+100;
    }
    void func12b_member(int& r, const int i) noexcept {
        r = i+1000;
    }
    static void Func13a_static(int& r, const int i) {
        r = i+100;
    }
    static void Func13b_static(int& r, const int i) noexcept {
        r = i+1000;
    }
 
    void func20a_member() {
        
    }
    static void Func20a_static() {
        
    }
 
        static int i = 100;
            return i + a;
        };
        return f;
    }
        int i = 100;
            return i + a;
        };
        return f;
    }
 
};
 
void test00_usage()
Unit test covering most variants of jau::function<R(A...)
Class template jau::function is a general-purpose static-polymorphic function wrapper.
static constexpr const bool limited_lambda_id
Static constexpr boolean indicating whether resulting type_info uniqueness is limited for lambda func...
consteval_cxx20 bool is_rtti_available() noexcept
Returns true if compiled with RTTI available.
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.
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 ...
@ lambda
Denotes a func::lambda_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.
@ ylambda
Denotes a func::ylambda_target_t.
METHOD_AS_TEST_CASE(TestByteStream01::test00a_protocols_error, "test00a_protocols_error")
bool operator!=(const Addr48Bit &lhs, const Addr48Bit &rhs) noexcept
bool operator==(const Addr48Bit &lhs, const Addr48Bit &rhs) noexcept
static std::string impl_name