#pragma once #include #include class FunctionCallException : public std::logic_error { public: FunctionCallException() : logic_error("FunctionCallException") { } }; template class Function; #define DEFINE_FUNC \ template \ class Function \ { \ class ICallable \ { \ public: \ virtual ~ICallable() \ { \ } \ \ virtual TRet operator()(ARGS_DECL) const = 0; \ virtual ICallable* Clone() const = 0; \ }; \ \ template \ class CallableImpl : public ICallable \ { \ public: \ explicit CallableImpl(TObject obj) : m_Object(obj) \ { \ } \ \ virtual TRet operator()(ARGS_DECL) const \ { \ return m_Object(ARGS); \ } \ \ virtual ICallable* Clone() const \ { \ return new CallableImpl(m_Object); \ } \ \ private: \ TObject m_Object; \ }; \ \ public: \ Function() : m_pCallable(NULL) \ { \ } \ \ template \ Function(TObject obj) : m_pCallable(new CallableImpl(obj)) \ { \ } \ \ Function(const Function& rhs) : m_pCallable(rhs.m_pCallable ? rhs.m_pCallable->Clone() : NULL) \ { \ } \ \ Function& operator=(const Function& rhs) \ { \ Function(rhs).Swap(*this); \ return *this; \ } \ \ void Swap(Function& rhs) \ { \ using std::swap; \ swap(m_pCallable, rhs.m_pCallable); \ } \ \ TRet operator()(ARGS_DECL) const \ { \ if (!m_pCallable) \ { \ throw FunctionCallException(); \ } \ \ return (*m_pCallable)(ARGS); \ } \ \ private: \ ICallable* m_pCallable; \ }; \ \ template \ class Function \ { \ class ICallable \ { \ public: \ virtual ~ICallable() \ { \ } \ \ virtual void operator()(ARGS_DECL) const = 0; \ virtual ICallable* Clone() const = 0; \ }; \ \ template \ class CallableImpl : public ICallable \ { \ public: \ explicit CallableImpl(TObject obj) : m_Object(obj) \ { \ } \ \ virtual void operator()(ARGS_DECL) const \ { \ m_Object(ARGS); \ } \ \ virtual ICallable* Clone() const \ { \ return new CallableImpl(m_Object); \ } \ \ private: \ TObject m_Object; \ }; \ \ public: \ Function() : m_pCallable(NULL) \ { \ } \ \ template \ Function(TObject obj) : m_pCallable(new CallableImpl(obj)) \ { \ } \ \ Function(const Function& rhs) : m_pCallable(rhs.m_pCallable ? rhs.m_pCallable->Clone() : NULL) \ { \ } \ \ Function& operator=(const Function& rhs) \ { \ Function(rhs).Swap(*this); \ return *this; \ } \ \ void Swap(Function& rhs) \ { \ using std::swap; \ swap(m_pCallable, rhs.m_pCallable); \ } \ \ void operator()(ARGS_DECL) const \ { \ if (!m_pCallable) \ { \ throw FunctionCallException(); \ } \ \ (*m_pCallable)(ARGS); \ } \ \ private: \ ICallable* m_pCallable; \ }; // 0 #define TYPENAMES_DECL_C #define TYPENAMES_DECL #define TYPES #define ARGS_DECL #define ARGS DEFINE_FUNC #undef TYPENAMES_DECL_C #undef TYPENAMES_DECL #undef TYPES #undef ARGS_DECL #undef ARGS // --- #define TYPENAMES_DECL_C , // 1 #define TYPENAMES_DECL typename TArg1 #define TYPES TArg1 #define ARGS_DECL TArg1 arg1 #define ARGS arg1 DEFINE_FUNC #undef TYPENAMES_DECL #undef TYPES #undef ARGS_DECL #undef ARGS // 2 #define TYPENAMES_DECL typename TArg1, typename TArg2 #define TYPES TArg1, TArg2 #define ARGS_DECL TArg1 arg1, TArg2 arg2 #define ARGS arg1, arg2 DEFINE_FUNC #undef TYPENAMES_DECL #undef TYPES #undef ARGS_DECL #undef ARGS // 3 #define TYPENAMES_DECL typename TArg1, typename TArg2, typename TArg3 #define TYPES TArg1, TArg2, TArg3 #define ARGS_DECL TArg1 arg1, TArg2 arg2, TArg3 arg3 #define ARGS arg1, arg2, arg3 DEFINE_FUNC #undef TYPENAMES_DECL #undef TYPES #undef ARGS_DECL #undef ARGS // 4 #define TYPENAMES_DECL typename TArg1, typename TArg2, typename TArg3, typename TArg4 #define TYPES TArg1, TArg2, TArg3, TArg4 #define ARGS_DECL TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4 #define ARGS arg1, arg2, arg3, arg4 DEFINE_FUNC #undef TYPENAMES_DECL #undef TYPES #undef ARGS_DECL #undef ARGS // --- #undef TYPENAMES_DECL_C template void swap(Function& lhs, Function& rhs) { lhs.Swap(rhs); }