Created
December 31, 2015 01:02
-
-
Save xaxxon/6a893dd60b6cfedc6e3f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template<typename METHOD_TYPE> | |
struct RunMethod {}; | |
template<typename RETURN_TYPE, typename CLASS_TYPE, typename ... PARAMETERS> | |
struct RunMethod<RETURN_TYPE(CLASS_TYPE::*)(PARAMETERS...)>{ | |
typedef RETURN_TYPE(CLASS_TYPE::*METHOD_TYPE)(PARAMETERS...); | |
CLASS_TYPE & object; | |
METHOD_TYPE method; | |
RunMethod(CLASS_TYPE & object, METHOD_TYPE method) : object(object), method(method) {} | |
void operator()(const v8::FunctionCallbackInfo<v8::Value> & info, PARAMETERS... parameters) { | |
RETURN_TYPE return_value = (object.*method)(parameters...); | |
CastToJS<RETURN_TYPE> cast; | |
info.GetReturnValue().Set(cast(info.GetIsolate(), return_value)); | |
} | |
}; | |
template<typename CLASS_TYPE, typename ... PARAMETERS> | |
struct RunMethod<void(CLASS_TYPE::*)(PARAMETERS...)> { | |
typedef void(CLASS_TYPE::*METHOD_TYPE)(PARAMETERS...); | |
CLASS_TYPE & object; | |
METHOD_TYPE method; | |
RunMethod(CLASS_TYPE & object, METHOD_TYPE method) : object(object), method(method) {} | |
void operator()(const v8::FunctionCallbackInfo<v8::Value> &, PARAMETERS... parameters) { | |
(object.*method)(parameters...); | |
} | |
}; | |
// calls an object method | |
template<int depth, typename T, typename U> | |
class Caller {}; | |
// specialization for when there are no remaining parameters for the method | |
template<int depth, typename METHOD_TYPE, typename RET, typename CLASS_TYPE> | |
class Caller<depth, METHOD_TYPE, RET(CLASS_TYPE::*)()> { | |
public: | |
// the final class in the call chain stores the actual method to be called | |
METHOD_TYPE method; | |
Caller(METHOD_TYPE method):method(method){} | |
enum {DEPTH=depth, ARITY=0}; | |
// This call method actually calls the method with the specified object and the | |
// parameter pack that was built up via the chain of calls between templated types | |
template<typename ... Ts> | |
void call(CLASS_TYPE & object, const v8::FunctionCallbackInfo<v8::Value> & info, Ts... ts) { | |
RunMethod<METHOD_TYPE> run_method(object, this->method); | |
run_method(info, ts...); | |
} | |
}; | |
// specialization that strips off the first remaining parameter off the method type, stores that and then | |
// inherits from another instance that either strips the next one off, or if none remaining, actually calls | |
// the method | |
// The method type is specified twice because the first is actually used by the final specialization to hold the | |
// method type while the second one has its input parameter list stripped off one at a time to determine when | |
// the inheritance chain ends | |
template<int depth, typename METHOD_TYPE, typename CLASS_TYPE, typename RET, typename HEAD, typename...TAIL> | |
class Caller<depth, METHOD_TYPE, RET(CLASS_TYPE::*)(HEAD,TAIL...)> : public Caller<depth+1, METHOD_TYPE, RET(CLASS_TYPE::*)(TAIL...)> { | |
public: | |
typedef Caller<depth+1, METHOD_TYPE, RET(CLASS_TYPE::*)(TAIL...)> super; | |
typedef RET return_type; | |
enum {DEPTH = depth, ARITY=super::ARITY + 1}; | |
Caller(METHOD_TYPE func):super(func) {printf("Depth: %d\n", DEPTH);} | |
template<typename ... Ts> | |
void call(CLASS_TYPE & object, const v8::FunctionCallbackInfo<v8::Value> & info, Ts... ts) { | |
CastToNative<HEAD> cast; | |
printf("Caller call about to recurse\n"); | |
this->super::call(object, info, ts..., cast(info[depth])); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment