#ifndef __FUNCTION_H__ #define __FUNCTION_H__ #include "r.h" #include #include "lambda_trait.h" template class DelegateBase { public: typedef T ResultType; DelegateBase() { } virtual ~DelegateBase() { } virtual R operator () () = 0; }; template class Delegate1Base { public: typedef T ResultType; typedef T1 Arg1Type; Delegate1Base() { } virtual ~Delegate1Base() { } virtual R operator () (R arg) = 0; }; template class Delegate2Base { public: typedef T ResultType; typedef T1 Arg1Type; typedef T2 Arg2Type; Delegate2Base() { } virtual ~Delegate2Base() { } virtual R operator () (R arg1, R arg2) = 0; }; template class FunBase : public DelegateBase { public: typedef R (*FunType)(); FunBase(FunType fun) : DelegateBase(), fun(fun) { } virtual ~FunBase() { } virtual R operator () () override { return fun(); } private: FunType fun; }; template class FunLBase : public DelegateBase { public: typedef TFun FunType; FunLBase(FunType fun) : DelegateBase(), fun(fun) { } virtual ~FunLBase() { } virtual R operator () () override { return fun(); } private: FunType fun; }; template class Funx1Base : public DelegateBase { public: typedef R (*FunType)(R); Funx1Base(FunType fun, R arg1) : DelegateBase(), fun(fun), arg1(arg1) { } virtual ~Funx1Base() { } virtual R operator () () override { return fun(arg1); } protected: FunType fun; R arg1; }; template class Funx1LBase : public DelegateBase { public: typedef TFun FunType; Funx1LBase(FunType fun, R arg1) : DelegateBase(), fun(fun), arg1(arg1) { } virtual ~Funx1LBase() { } virtual R operator () () override { return fun(arg1); } protected: FunType fun; R arg1; }; template class Funx2Base : public DelegateBase { public: typedef R (*FunType)(R, R); Funx2Base(FunType fun, R arg1, R arg2) : DelegateBase(), fun(fun), arg1(arg1), arg2(arg2) { } virtual ~Funx2Base() { } virtual R operator () () override { return fun(arg1, arg2); } protected: FunType fun; R arg1; R arg2; }; template class Funx2LBase : public DelegateBase { public: Funx2LBase(TFun fun, R arg1, R arg2) : DelegateBase(), fun(fun), arg1(arg1), arg2(arg2) { } virtual ~Funx2LBase() { } virtual R operator () () override { return fun(arg1, arg2); } protected: TFun fun; R arg1; R arg2; }; template class Funx3Base : public DelegateBase { public: typedef R (*FunType)(R, R, R); Funx3Base(FunType fun, R arg1, R arg2, R arg3) : DelegateBase(), fun(fun), arg1(arg1), arg2(arg2), arg3(arg3) { } virtual ~Funx3Base() { } virtual R operator () () override { return fun(arg1, arg2, arg3); } protected: FunType fun; R arg1; R arg2; R arg3; }; template class Funx3LBase : public DelegateBase { public: typedef TFun FunType; Funx3LBase(FunType fun, R arg1, R arg2, R arg3) : DelegateBase(), fun(fun), arg1(arg1), arg2(arg2), arg3(arg3) { } virtual ~Funx3LBase() { } virtual R operator () () override { return fun(arg1, arg2, arg3); } protected: FunType fun; R arg1; R arg2; R arg3; }; /**** 1 arg ****/ template class Fun1Base : public Delegate1Base { public: typedef R (*FunType)(R); Fun1Base(FunType fun) : Delegate1Base(), fun(fun) { } virtual ~Fun1Base() { } virtual R operator() (R arg) override { return fun(arg); } protected: FunType fun; }; template class Fun1LBase : public Delegate1Base { public: typedef TFun FunType; Fun1LBase(FunType fun) : Delegate1Base(), fun(fun) { } virtual ~Fun1LBase() { } virtual R operator() (R arg) override { return fun(arg); } protected: FunType fun; }; template class Fun1x1Base : public Delegate1Base { public: typedef R (*FunType)(R, R); Fun1x1Base(FunType fun, R arg1) : Delegate1Base(), fun(fun), arg1(arg1) { } virtual ~Fun1x1Base() { } virtual R operator () (R arg) override { return fun(arg1, arg); } protected: FunType fun; R arg1; }; template class Fun1x1LBase : public Delegate1Base { public: typedef TFun FunType; Fun1x1LBase(FunType fun, R arg1) : Delegate1Base(), fun(fun), arg1(arg1) { } virtual ~Fun1x1LBase() { } virtual R operator () (R arg) override { return fun(arg1, arg); } protected: FunType fun; R arg1; }; /**** 2 args ****/ template class Fun2Base : public Delegate2Base { public: typedef R (*FunType)(R, R); Fun2Base(FunType fun) : Delegate2Base(), fun(fun) { } virtual ~Fun2Base() { } virtual R operator() (R arg1, R arg2) override { return fun(arg1, arg2); } protected: FunType fun; }; template class Fun2LBase : public Delegate2Base { public: typedef TFun FunType; Fun2LBase(FunType fun) : Delegate2Base(), fun(fun) { } virtual ~Fun2LBase() { } virtual R operator() (R arg1, R arg2) override { return fun(arg1, arg2); } protected: FunType fun; }; /**** refrence specializations to add more functionality ****/ template class R, true> : public R, false> { protected: // passing protected constructors inline R(int i) : R< DelegateBase, false >(i) { } public: // passing public constructors inline R() : R< DelegateBase, false>() { } template inline R(R& o) : R< DelegateBase, false>(o, 0) { _assert_subclass> ERRORBase; // U must be subclass of DelegateBase _assert_subclass ERRORItem; // result must be subclass of T } template inline R(R&& o) : R< DelegateBase, false>(o, 0) { _assert_subclass> ERRORBase; // U must be subclass of DelegateBase _assert_subclass ERRORItem; // result must be subclass of T } // passing operator= template inline R< DelegateBase, true >& operator=(R< DelegateBase, od >&& o) { R< DelegateBase, false >::operator=(o); return *this; } template inline R< DelegateBase, true >& operator=(R< DelegateBase, od >& o) { R< DelegateBase, false >::operator=(o); return *this; } // additional functionality inline R operator() () { return this->deref()(); } // keep reference makeable with Ref::mk friend class Ref; }; template class R, true> : public R, false> { protected: // passing protected constructors inline R(int i) : R< Delegate1Base, false >(i) { } public: // passing public constructors inline R() : R< Delegate1Base, false>() { } template inline R(R& o) : R< Delegate1Base, false>(o, 0) { _assert_subclass> ERRORBase; // U must be subclass of DelegateBase _assert_subclass ERRORItem; // result must be subclass of T _assert_subclass ERRORArg1; // result must be subclass of T } template inline R(R&& o) : R< Delegate1Base, false>(o, 0) { _assert_subclass> ERRORBase; // U must be subclass of DelegateBase _assert_subclass ERRORItem; // result must be subclass of T _assert_subclass ERRORArg1; // result must be subclass of T } // passing operator= template inline R< Delegate1Base, true >& operator=(R< Delegate1Base, od >&& o) { R< DelegateBase, false >::operator=(o); return *this; } template inline R< Delegate1Base, true >& operator=(R< Delegate1Base, od >& o) { R< DelegateBase, false >::operator=(o); return *this; } // additional functionality inline R operator() (R arg1) { return this->deref()(arg1); } // keep reference makeable with Ref::mk friend class Ref; }; template class R, true> : public R, false> { protected: // passing protected constructors inline R(int i) : R< Delegate2Base, false >(i) { } public: // passing public constructors inline R() : R< Delegate2Base, false>() { } template inline R(R& o) : R< Delegate2Base, false>(o, 0) { _assert_subclass> ERRORBase; // U must be subclass of DelegateBase _assert_subclass ERRORItem; // result must be subclass of T _assert_subclass ERRORArg1; // arg must be superclass of T _assert_subclass ERRORArg2; // arg must be superclass of T } template inline R(R&& o) : R< Delegate2Base, false>(o, 0) { _assert_subclass> ERRORBase; // U must be subclass of DelegateBase _assert_subclass ERRORItem; // result must be subclass of T _assert_subclass ERRORArg1; // arg must be superclass of T _assert_subclass ERRORArg2; // arg must be superclass of T } // passing operator= template inline R< Delegate2Base, true >& operator=(R< Delegate2Base, od >&& o) { R< DelegateBase, false >::operator=(o); return *this; } template inline R< Delegate2Base, true >& operator=(R< Delegate2Base, od >& o) { R< DelegateBase, false >::operator=(o); return *this; } // additional functionality inline R operator() (R arg1, R arg2) { return this->deref()(arg1, arg2); } // keep reference makeable with Ref::mk friend class Ref; }; /**** type aliases ****/ template using Delegate = R< DelegateBase >; template using Delegate1 = R< Delegate1Base >; template using Delegate2 = R< Delegate2Base >; template using Fun = R< FunBase >; template using Funx1 = R< Funx1Base >; template using Funx2 = R< Funx2Base >; template using Funx2L = R< Funx2LBase >; template using Funx3 = R< Funx3Base >; template Delegate mkFun(R (*fun)()) { return Ref::mk< FunBase, typename FunBase::FunType >(fun); } template auto mkLFun(TFun fun) -> Delegate { return Ref::mk> (fun); } template Delegate mkFun(R (*fun)(R), R arg1) { return Ref::mk< Funx1Base, typename Funx1Base::FunType, R >(fun, arg1); } template auto mkLFun(TFun fun, R arg1) -> Delegate { return Ref::mk, TFun, R> (fun, arg1); } template Delegate mkFun(R (*fun)(R, R), R arg1, R arg2) { return Ref::mk< Funx2Base, typename Funx2Base::FunType, R, R >(fun, arg1, arg2); } template auto mkLFun(TFun fun, R arg1, R arg2) -> Delegate { return Ref::mk< Funx2LBase< typename decltype(fun(arg1, arg2))::etype, T1, T2, TFun>, TFun, R, R >(fun, arg1, arg2); } template Delegate mkFun(R (*fun)(R, R, R), R arg1, R arg2, R arg3) { return Ref::mk< Funx3Base, typename Funx3Base::FunType, R, R, R >(fun, arg1, arg2, arg3); } template auto mkLFun(TFun fun, R arg1, R arg2, R arg3) -> Delegate { return Ref::mk, TFun, R, R, R>(fun, arg1, arg2, arg3); } /**** 1 arg ****/ template Delegate1 mkFun1(R (*fun)(R)) { return Ref::mk< Fun1Base, typename Fun1Base::FunType >(fun); } template auto mkLFun1(TFun fun) -> Delegate1::return_type::etype, typename lambdatype::arg1_type::etype> { return Ref::mk::return_type::etype, typename lambdatype::arg1_type::etype, TFun>, TFun>(fun); } template Delegate1 mkFun1(R (*fun)(R, R), R arg) { return Ref::mk< Fun1x1Base, typename Fun1x1Base::FunType, R >(fun, arg); } template auto mkLFun1(TFun fun, R arg1) -> Delegate1::return_type::etype, typename lambdatype::arg2_type::etype> { return Ref::mk::return_type::etype, typename lambdatype::arg2_type::etype, TArg1, TFun>, TFun, R>(fun, arg1); } /**** 2 args ****/ template Delegate2 mkFun2(R (*fun)(R, R)) { return Ref::mk< Fun2Base, typename Fun2Base::FunType >(fun); } template auto mkLFun2(TFun fun) -> Delegate2::return_type::etype, typename lambdatype::arg1_type::etype, typename lambdatype::arg2_type::etype> { return Ref::mk::return_type::etype, typename lambdatype::arg1_type::etype, typename lambdatype::arg2_type::etype, TFun>, TFun>(fun); } #endif