Skip to content

Instantly share code, notes, and snippets.

@xaxxon
Created December 31, 2015 01:02
Show Gist options
  • Save xaxxon/6a893dd60b6cfedc6e3f to your computer and use it in GitHub Desktop.
Save xaxxon/6a893dd60b6cfedc6e3f to your computer and use it in GitHub Desktop.
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