I have a simple situation that probably requires a difficult way to solve, but I'm not sure about that.
I basically have this object that encapsulated a member function:
template<class T, typename R, typename... ARGS>
class MemberFunction
{
private:
using function_type = R (T::*)(ARGS...);
function_type function;
public:
MemberFunction(function_type function) : function(function) { }
void call(T* object, ARGS&&... args)
{
(object->*function)(args...);
}
};
It can be used easily.
MemberFunction<Foo, int, int, int> function(&Foo::add)
Foo foo;
int res = function.call(&foo, 10,20)
The problem is that I would like to call it, going through a custom environment that uses a value stack to control this method, this translates to the following code:
int arg2 = stack.pop().as<int>();
int arg1 = stack.pop().as<int>();
Foo* object = stack.pop().as<Foo*>();
int ret = function.call(object, arg1, arg2);
stack.push(Value(int));
This is easy to do directly in the code, but I would like to find a way to encapsulate this behavior directly in the class MemberFunction, exposing one method void call(Stack& stack)that does the work for me to get something like:
MemberFunction<Foo, int, int, int> function(&Foo::add);
Stack stack;
stack.push(Value(new Foo());
stack.push(10);
stack.push(20);
function.call(stack);
assert(stack.pop().as<int>() == Foo{}.add(10,20));
But since I'm new to variable templates, I don't know how I could do this efficiently and elegantly.
EDIT: Stack StackValue
, , std::stack<StackValue>, push pop , -
struct StackValue
{
union
{
float fvalue;
s32 ivalue;
bool bvalue;
FloatPair fpair;
IntPair ipair;
void* ptr;
};
template<typename T> T as();
template<typename T> StackValue(T type);
StackValue() { }
};
template<> inline StackValue::StackValue(float f) : fvalue(f) { }
template<> inline StackValue::StackValue(s32 i) : ivalue(i) { }
...
template<> inline float StackValue::as<float>() { return fvalue; }
template<> inline s32 StackValue::as<s32>() { return ivalue; }
...
class Stack
{
private:
std::stack<StackValue> stack;
public:
StackValue& peek() { return stack.top(); }
StackValue pop() { StackValue v = stack.top(); stack.pop(); return v; }
void push(StackValue value) { stack.push(value); }
template<typename T> void pushValue(T value) { stack.push(StackValue(value)); }
template<typename T> T popValue() {
StackValue v = stack.top().as<T>();
stack.pop();
return v;
}
}