Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <unordered_map>
- #include <string>
- #include <iostream>
- #include <stdexcept>
- #include <memory>
- #include <typeinfo>
- namespace dynamic_call {
- struct function_not_found : std::invalid_argument {
- explicit function_not_found(const std::string& msg)
- : std::invalid_argument(msg.c_str()) {}
- explicit function_not_found(const char* msg)
- : std::invalid_argument(msg) {}
- };
- struct function_type_unmatched : std::invalid_argument {
- explicit function_type_unmatched(const std::string& msg)
- : std::invalid_argument(msg.c_str()) {}
- explicit function_type_unmatched(const char* msg)
- : std::invalid_argument(msg) {}
- };
- struct func_type {
- virtual ~func_type() {};
- };
- template <typename FuncType>
- struct func_type_holder : func_type {
- explicit func_type_holder(FuncType fn) : fn_(fn) {}
- FuncType fn_;
- };
- template <typename ResType>
- struct func_call_impl {
- explicit func_call_impl(func_type& func_) : func(func_) {}
- public:
- template <typename... T>
- ResType operator ()(T... t) const {
- auto* pFTH = dynamic_cast<func_type_holder<ResType(*)(T...)>*>(&func);
- if (!pFTH)
- throw function_type_unmatched(typeid(ResType(*)(T...)).name());
- return pFTH->fn_(t...);
- }
- private:
- func_type& func;
- };
- template <typename ResType, typename ObjType>
- struct mem_func_call_impl {
- mem_func_call_impl(ObjType& obj_, func_type& mem_func_) : obj(obj_), mem_func(mem_func_) {}
- public:
- template <typename... T>
- ResType operator ()(T... t) const {
- auto* pFTH = dynamic_cast<func_type_holder<ResType(ObjType::*)(T...)>*>(&mem_func);
- if (!pFTH)
- throw function_type_unmatched(typeid(ResType(ObjType::*)(T...)).name());
- return (obj.*(pFTH->fn_))(t...);
- }
- private:
- ObjType& obj;
- func_type& mem_func;
- };
- template <typename ResType, typename ObjType>
- struct mem_func_call_impl<ResType, const ObjType> {
- mem_func_call_impl(const ObjType& obj_, func_type& mem_func_) : obj(obj_), mem_func(mem_func_) {}
- public:
- template <typename... T>
- ResType operator ()(T... t) const {
- auto* pFTH = dynamic_cast<func_type_holder<ResType(ObjType::*)(T...) const>*>(&mem_func);
- if (!pFTH)
- throw function_type_unmatched(typeid(ResType(ObjType::*)(T...) const).name());
- return (obj.*(pFTH->fn_))(t...);
- }
- private:
- const ObjType& obj;
- func_type& mem_func;
- };
- class dynamic_call {
- typedef std::unordered_map<std::string, std::unique_ptr<func_type>> ContType;
- public:
- template <typename FuncType>
- bool regFunc(FuncType pfn, std::string fnName) {
- // Return true if succeeded
- return funcs_.emplace(std::move(fnName), std::make_unique<func_type_holder<FuncType>>(pfn)).second;
- }
- bool unregFunc(const std::string& fnName) {
- auto it = funcs_.find(fnName);
- if (it == funcs_.end())
- return false;
- funcs_.erase(it);
- // Return true if succeeded
- return true;
- }
- template <typename ResType>
- func_call_impl<ResType> callFunc(const std::string& fnName) const {
- auto it = funcs_.find(fnName);
- if (it == funcs_.end())
- throw function_not_found(fnName);
- return func_call_impl<ResType>(*it->second);
- }
- template <typename ResType, typename ObjType>
- mem_func_call_impl<ResType, ObjType> callMemFunc(const std::string& fnName, ObjType& obj) const {
- auto it = funcs_.find(fnName);
- if (it == funcs_.end())
- throw function_not_found(fnName);
- return mem_func_call_impl<ResType, ObjType>(obj, *it->second);
- }
- private:
- ContType funcs_;
- };
- }
- #define REG_FUNC(func) regFunc(func, #func)
- #define REG_MEM_FUNC(mem_func) regFunc(&mem_func, #mem_func)
- void fn() {
- std::cout << "fn() is called" << std::endl;
- }
- struct A {
- A(int i_) : i(i_) {};
- int fn1(int a) const {
- std::cout << "A::fn1(" << a << ") is called, with A::i=" << i << std::endl;
- return a + i;
- }
- void fn2() {
- std::cout << "This should not be displayed" << std::endl;
- i = 2;
- }
- int i;
- };
- int main() {
- using namespace std;
- dynamic_call::dynamic_call fns;
- fns.REG_MEM_FUNC(A::fn1);
- fns.REG_FUNC(fn);
- fns.REG_MEM_FUNC(A::fn2);
- const A a(10);
- int res = fns.callMemFunc<int>("A::fn1", a)(10);
- cout << "Result of A::fn1 = " << res << endl;
- fns.callFunc<void>("fn")();
- try {
- fns.callMemFunc<void>("A::fn2", a)();
- } catch (dynamic_call::function_type_unmatched& e) {
- cout << "Exception catched with type of function_type_unmatched: " << e.what() << endl;
- }
- fns.unregFunc("fn");
- try {
- fns.callFunc<void>("fn")();
- } catch (dynamic_call::function_not_found& e) {
- cout << "Exception catched with type of function_not_found: " << e.what() << endl;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement