Advertisement
zhangsongcui

Dynamic Call V1.1

Mar 31st, 2014
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.34 KB | None | 0 0
  1. #include <unordered_map>
  2. #include <string>
  3. #include <iostream>
  4. #include <stdexcept>
  5. #include <memory>
  6. #include <typeinfo>
  7.  
  8. namespace dynamic_call {
  9.     struct function_not_found : std::invalid_argument {
  10.         explicit function_not_found(const std::string& msg)
  11.             : std::invalid_argument(msg.c_str()) {}
  12.         explicit function_not_found(const char* msg)
  13.             : std::invalid_argument(msg) {}
  14.     };
  15.  
  16.     struct function_type_unmatched : std::invalid_argument {
  17.         explicit function_type_unmatched(const std::string& msg)
  18.             : std::invalid_argument(msg.c_str()) {}
  19.         explicit function_type_unmatched(const char* msg)
  20.             : std::invalid_argument(msg) {}
  21.     };
  22.  
  23.     struct func_type {
  24.         virtual ~func_type() {};
  25.     };
  26.  
  27.     template <typename FuncType>
  28.     struct func_type_holder : func_type {
  29.         explicit func_type_holder(FuncType fn) : fn_(fn) {}
  30.         FuncType fn_;
  31.     };
  32.  
  33.     template <typename ResType>
  34.     struct func_call_impl {
  35.         explicit func_call_impl(func_type& func_) : func(func_) {}
  36.  
  37.     public:
  38.         template <typename... T>
  39.         ResType operator ()(T... t) const {
  40.             auto* pFTH = dynamic_cast<func_type_holder<ResType(*)(T...)>*>(&func);
  41.             if (!pFTH)
  42.                 throw function_type_unmatched(typeid(ResType(*)(T...)).name());
  43.             return pFTH->fn_(t...);
  44.         }
  45.  
  46.     private:
  47.         func_type& func;
  48.     };
  49.  
  50.     template <typename ResType, typename ObjType>
  51.     struct mem_func_call_impl {
  52.         mem_func_call_impl(ObjType& obj_, func_type& mem_func_) : obj(obj_), mem_func(mem_func_) {}
  53.  
  54.     public:
  55.         template <typename... T>
  56.         ResType operator ()(T... t) const {
  57.             auto* pFTH = dynamic_cast<func_type_holder<ResType(ObjType::*)(T...)>*>(&mem_func);
  58.             if (!pFTH)
  59.                 throw function_type_unmatched(typeid(ResType(ObjType::*)(T...)).name());
  60.             return (obj.*(pFTH->fn_))(t...);
  61.         }
  62.  
  63.     private:
  64.         ObjType& obj;
  65.         func_type& mem_func;
  66.     };
  67.  
  68.     template <typename ResType, typename ObjType>
  69.     struct mem_func_call_impl<ResType, const ObjType> {
  70.         mem_func_call_impl(const ObjType& obj_, func_type& mem_func_) : obj(obj_), mem_func(mem_func_) {}
  71.  
  72.     public:
  73.         template <typename... T>
  74.         ResType operator ()(T... t) const {
  75.             auto* pFTH = dynamic_cast<func_type_holder<ResType(ObjType::*)(T...) const>*>(&mem_func);
  76.             if (!pFTH)
  77.                 throw function_type_unmatched(typeid(ResType(ObjType::*)(T...) const).name());
  78.             return (obj.*(pFTH->fn_))(t...);
  79.         }
  80.  
  81.     private:
  82.         const ObjType& obj;
  83.         func_type& mem_func;
  84.     };
  85.  
  86.     class dynamic_call {
  87.         typedef std::unordered_map<std::string, std::unique_ptr<func_type>> ContType;
  88.  
  89.     public:
  90.         template <typename FuncType>
  91.         bool regFunc(FuncType pfn, std::string fnName) {
  92.             // Return true if succeeded
  93.             return funcs_.emplace(std::move(fnName), std::make_unique<func_type_holder<FuncType>>(pfn)).second;
  94.         }
  95.  
  96.         bool unregFunc(const std::string& fnName) {
  97.             auto it = funcs_.find(fnName);
  98.             if (it == funcs_.end())
  99.                 return false;
  100.             funcs_.erase(it);
  101.             // Return true if succeeded
  102.             return true;
  103.         }
  104.  
  105.         template <typename ResType>
  106.         func_call_impl<ResType> callFunc(const std::string& fnName) const {
  107.             auto it = funcs_.find(fnName);
  108.             if (it == funcs_.end())
  109.                 throw function_not_found(fnName);
  110.             return func_call_impl<ResType>(*it->second);
  111.         }
  112.  
  113.         template <typename ResType, typename ObjType>
  114.         mem_func_call_impl<ResType, ObjType> callMemFunc(const std::string& fnName, ObjType& obj) const {
  115.             auto it = funcs_.find(fnName);
  116.             if (it == funcs_.end())
  117.                 throw function_not_found(fnName);
  118.             return mem_func_call_impl<ResType, ObjType>(obj, *it->second);
  119.         }
  120.  
  121.     private:
  122.         ContType funcs_;
  123.     };
  124. }
  125. #define REG_FUNC(func) regFunc(func, #func)
  126. #define REG_MEM_FUNC(mem_func) regFunc(&mem_func, #mem_func)
  127.  
  128. void fn() {
  129.     std::cout << "fn() is called" << std::endl;
  130. }
  131.  
  132. struct A {
  133.     A(int i_) : i(i_) {};
  134.     int fn1(int a) const {
  135.         std::cout << "A::fn1(" << a << ") is called, with A::i=" << i << std::endl;
  136.         return a + i;
  137.     }
  138.  
  139.     void fn2() {
  140.         std::cout << "This should not be displayed" << std::endl;
  141.         i = 2;
  142.     }
  143.  
  144.     int i;
  145. };
  146.  
  147. int main() {
  148.     using namespace std;
  149.     dynamic_call::dynamic_call fns;
  150.     fns.REG_MEM_FUNC(A::fn1);
  151.     fns.REG_FUNC(fn);
  152.     fns.REG_MEM_FUNC(A::fn2);
  153.     const A a(10);
  154.  
  155.     int res = fns.callMemFunc<int>("A::fn1", a)(10);
  156.     cout << "Result of A::fn1 = " << res << endl;
  157.  
  158.     fns.callFunc<void>("fn")();
  159.  
  160.     try {
  161.         fns.callMemFunc<void>("A::fn2", a)();
  162.     } catch (dynamic_call::function_type_unmatched& e) {
  163.         cout << "Exception catched with type of function_type_unmatched: " << e.what() << endl;
  164.     }
  165.  
  166.     fns.unregFunc("fn");
  167.  
  168.     try {
  169.         fns.callFunc<void>("fn")();
  170.     } catch (dynamic_call::function_not_found& e) {
  171.         cout << "Exception catched with type of function_not_found: " << e.what() << endl;
  172.     }
  173. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement