Last active
May 19, 2016 09:23
-
-
Save pperehozhih/f26ffe25e8c0387d8ce8f03154f35cb5 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> | |
template <std::size_t... I> | |
class index_sequence {}; | |
template <std::size_t N, std::size_t ...I> | |
struct make_index_sequence : make_index_sequence<N-1, N-1,I...> {}; | |
template <std::size_t ...I> | |
struct make_index_sequence<0,I...> : index_sequence<I...> {}; | |
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