Created
September 1, 2016 09:05
-
-
Save pperehozhih/d3db8bb058ecbd8152922fd920410bdb 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
#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