Skip to content

Instantly share code, notes, and snippets.

@pperehozhih
Created September 1, 2016 09:05
Show Gist options
  • Save pperehozhih/d3db8bb058ecbd8152922fd920410bdb to your computer and use it in GitHub Desktop.
Save pperehozhih/d3db8bb058ecbd8152922fd920410bdb to your computer and use it in GitHub Desktop.
#include <iostream>
#include <stack>
#include <cassert>
struct BaseValue {
virtual ~BaseValue() {}
};
template<typename T>
struct Value : public BaseValue{
T obj;
static std::shared_ptr<BaseValue> make_shared(T obj)
{
Value<T>* result = new Value<T>();
result->obj = obj;
return std::shared_ptr<BaseValue>(result);
}
};
typedef std::stack<std::shared_ptr<BaseValue> > Stack_;
typedef std::shared_ptr<Stack_> Stack;
struct BaseInvoker {
virtual void Invoke(void*, Stack){}
virtual ~BaseInvoker(){}
};
template<typename Class, typename Result, typename ...Args>
struct Invoker : public BaseInvoker {
typedef Result (Class::*Method)(Args...);
Method method;
Invoker(Method method):method(method){}
Result Execute(Class* cls, Args ...args){
return (cls->*method)(args...);
}
template<typename T>
T get(BaseValue* val){
Value<T>* v = dynamic_cast<Value<T>*>(val);
assert(v);
return v->obj;
}
template<typename std::size_t... I>
Result ExecuteInvoke(Class* cls, std::shared_ptr<BaseValue>* args, index_sequence<I...>) {
return Execute(cls, get<Args>(args[I].get())...);
}
virtual void Invoke(void* clss, Stack st){
Class* cls = (Class*)clss;
const std::size_t count = sizeof...(Args);
std::shared_ptr<BaseValue> args[count];
std::size_t index = count;
while(index != 0) {
args[count - index] = st->top();
st->pop();
--index;
}
st->push(Value<Result>::make_shared(ExecuteInvoke(cls, args, make_index_sequence<sizeof...(Args)>{})));
}
};
typedef std::shared_ptr<BaseInvoker> BaseInvokerPtr;
struct test{
int function_int(int a, int b){
return a + b;
}
int function_sqrt(int a){
return a * a;
}
void function_echo(int val){
std::cout << val << std::endl;
}
};
int main(int argc, char *argv[])
{
std::stack<BaseInvokerPtr> functions;
functions.push(BaseInvokerPtr(new Invoker<test, int, int>(&test::function_sqrt)));
functions.push(BaseInvokerPtr(new Invoker<test, int, int, int>(&test::function_int)));
Stack stask(new Stack_());
stask->push(Value<int>::make_shared(1));
stask->push(Value<int>::make_shared(2));
test t;
while(false == functions.empty()) {
functions.top()->Invoke(&t, stask);
functions.pop();
}
if (false == stask->empty()) {
Value<int>* result = dynamic_cast<Value<int>*>(stask->top().get());
std::cout << result->obj <<std::endl;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment