#ifndef SLANG_CORE_FUNC_PTR_H #define SLANG_CORE_FUNC_PTR_H #include "slang-smart-pointer.h" namespace Slang { template class FuncPtr : public RefObject { public: virtual TResult operator()(Arguments...) const = 0; virtual bool operator==(const FuncPtr*) { return false; } virtual FuncPtr* clone() = 0; virtual ~FuncPtr() {} }; template class CdeclFuncPtr : public FuncPtr { public: typedef TResult (*FuncType)(Arguments...); private: FuncType funcPtr; public: CdeclFuncPtr(FuncType func) : funcPtr(func) {} virtual FuncPtr* clone() override { auto rs = new CdeclFuncPtr(funcPtr); return rs; } virtual TResult operator()(Arguments... params) const override { return funcPtr(params...); } virtual bool operator==(const FuncPtr* ptr) override { auto cptr = dynamic_cast*>(ptr); if (cptr) return funcPtr == cptr->funcPtr; else return false; } }; template class MemberFuncPtr : public FuncPtr { public: typedef TResult (Class::*FuncType)(Arguments...); private: FuncType funcPtr; Class* object; public: MemberFuncPtr(Class* obj, FuncType func) : funcPtr(func) , object(obj) {} virtual FuncPtr* clone() override { auto rs = new MemberFuncPtr(object, funcPtr); return rs; } virtual TResult operator()(Arguments... params) const override { return (object->*funcPtr)(params...); } virtual bool operator==(const FuncPtr* ptr) override { auto cptr = dynamic_cast*>(ptr); if (cptr) return funcPtr == cptr->funcPtr && object == cptr->object; else return false; } }; template class LambdaFuncPtr : public FuncPtr { private: F func; public: LambdaFuncPtr(const F& _func) : func(_func) {} virtual TResult operator()(Arguments... params) const override { return func(params...); } virtual FuncPtr* clone() override { auto rs = new LambdaFuncPtr(func); return rs; } virtual bool operator==(const FuncPtr* /*ptr*/) override { return false; } }; template class Func { private: RefPtr> funcPtr; public: Func() {} Func(typename CdeclFuncPtr::FuncType func) { funcPtr = new CdeclFuncPtr(func); } template Func(Class* object, typename MemberFuncPtr::FuncType func) { funcPtr = new MemberFuncPtr(object, func); } template Func(const TFuncObj& func) { funcPtr = new LambdaFuncPtr(func); } Func& operator=(typename CdeclFuncPtr::FuncType func) { funcPtr = new CdeclFuncPtr(func); return *this; } template Func& operator=(const MemberFuncPtr& func) { funcPtr = new MemberFuncPtr(func); return *this; } template Func& operator=(const TFuncObj& func) { funcPtr = new LambdaFuncPtr(func); return *this; } bool operator==(const Func& f) { return *funcPtr == f.funcPtr.Ptr(); } bool operator!=(const Func& f) { return !(*this == f); } TResult operator()(Arguments... params) const { return (*funcPtr)(params...); } }; // template // using Action = Func; template class Action : public Func { private: RefPtr> funcPtr; public: Action() {} Action(const Action& proc) { funcPtr = proc.funcPtr; } Action(typename CdeclFuncPtr::FuncType func) { funcPtr = new CdeclFuncPtr(func); } template Action(Class* object, typename MemberFuncPtr::FuncType func) { funcPtr = new MemberFuncPtr(object, func); } template Action(const TFuncObj& func) { funcPtr = new LambdaFuncPtr(func); } Action& operator=(typename CdeclFuncPtr::FuncType func) { funcPtr = new CdeclFuncPtr(func); return *this; } template Action& operator=(const MemberFuncPtr& func) { funcPtr = new MemberFuncPtr(func); return *this; } template Action& operator=(const TFuncObj& func) { funcPtr = new LambdaFuncPtr(func); return *this; } Action& operator=(const Action& proc) { funcPtr = proc.funcPtr; return *this; } void clear() { funcPtr = nullptr; } void operator()(Arguments... params) const { if (funcPtr) (*funcPtr)(params...); } }; } // namespace Slang #endif