#pragma once
template<typename ReturnType, typename ...Params>
class FunctionBase {
public:
int referencecount;
FunctionBase():referencecount(1){}
virtual ReturnType operator()(Params... params)=0;
};
template<typename ReturnType, typename ...Params>
class CFunction : public FunctionBase<ReturnType, Params...> {
private:
ReturnType (*function)(Params...);
public:
CFunction(ReturnType (*func)(Params...)):function(func){}
virtual ReturnType operator()(Params... params){
return function(params...);
}
};
template<typename ClassType, typename ReturnType, typename ...Params>
class MemberFunction : public FunctionBase<ReturnType, Params...> {
private:
ClassType* _thisptr;
ReturnType (ClassType::*function)(Params...);
public:
MemberFunction(ClassType* thisptr, ReturnType (ClassType::*func)(Params...)):_thisptr(thisptr), function(func){}
virtual ReturnType operator()(Params... params){
return (_thisptr->*function)(params...);
}
};
template <typename ReturnType, typename ...Params>
class Function {
private:
FunctionBase<ReturnType, Params...>* function;
void destroy(){
function->referencecount--;
if(function->referencecount<=0){
delete function;
}
}
public:
//c function constructor
Function(ReturnType (*func)(Params...)){
function = new CFunction<ReturnType, Params...>(func);
}
//member function constructor
template<typename ClassType>
Function(ClassType* thisptr, ReturnType (ClassType::*func)(Params...)){
function = new MemberFunction<ClassType, ReturnType, Params...>(thisptr, func);
}
//copy constructor
Function(const Function& rhs) {
function = rhs.function;
function->referencecount++;
}
//assignment operator
Function& operator=(const Function& rhs) {
if(&rhs != this){
if(rhs->function != function){
destroy();
function = rhs.function;
function->referencecount++;
}
}
return *this;
}
ReturnType operator()(Params... params){
return (*function)(params...);
}
//destructor
~Function(){
destroy();
}
};