Advertisement
zhangsongcui

Dynamic Call

Dec 29th, 2011
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.94 KB | None | 0 0
  1. #include <map>
  2. #include <string>
  3. #include <iostream>
  4. #include <stdexcept>
  5.  
  6. namespace dynamic_call
  7. {
  8.     struct function_not_found: std::invalid_argument
  9.     {
  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.     {
  18.         explicit function_type_unmatched(const std::string& msg)
  19.             : std::invalid_argument(msg.c_str()) {}
  20.         explicit function_type_unmatched(const char* msg)
  21.             : std::invalid_argument(msg) {}
  22.     };
  23.  
  24.     struct func_type
  25.     {
  26.         virtual ~func_type() {};
  27.     };
  28.  
  29.     template <typename FuncType>
  30.     struct func_type_holder: func_type
  31.     {
  32.         func_type_holder(FuncType fn): fn_(fn) {}
  33.         FuncType fn_;
  34.     };
  35.  
  36.     template <typename ResType>
  37.     struct func_call_impl
  38.     {
  39.         func_call_impl(func_type& func_): func(func_) {}
  40.  
  41.     public:
  42.         ResType operator ()()
  43.         {
  44.             func_type_holder<ResType (*)()>* pFTH = dynamic_cast<func_type_holder<ResType (*)()>*>(&func);
  45.             if (pFTH == NULL)
  46.                 throw function_type_unmatched("func_call_impl::operator ()()");
  47.             return pFTH->fn_();
  48.         }
  49.  
  50.         template <typename T1>
  51.         ResType operator ()(T1 t1)
  52.         {
  53.             func_type_holder<ResType (*)(T1)>* pFTH = dynamic_cast<func_type_holder<ResType (*)(T1)>*>(&func);
  54.             if (pFTH == NULL)
  55.                 throw function_type_unmatched("func_call_impl::operator ()(T1)");
  56.             return pFTH->fn_(t1);
  57.         }
  58.  
  59.         template <typename T1, typename T2>
  60.         ResType operator ()(T1 t1, T2 t2)
  61.         {
  62.             func_type_holder<ResType (*)(T1, T2)>* pFTH = dynamic_cast<func_type_holder<ResType (*)(T1, T2)>*>(&func);
  63.             if (pFTH == NULL)
  64.                 throw function_type_unmatched("func_call_impl::operator ()(T1, T2)");
  65.             return pFTH->fn_(t1, t2);
  66.         }
  67.  
  68.         template <typename T1, typename T2, typename T3>
  69.         ResType operator ()(T1 t1, T2 t2, T3 t3)
  70.         {
  71.             func_type_holder<ResType (*)(T1, T2, T3)>* pFTH = dynamic_cast<func_type_holder<ResType (*)(T1, T2, T3)>*>(&func);
  72.             if (pFTH == NULL)
  73.                 throw function_type_unmatched("func_call_impl::operator ()(T1, T2, T3)");
  74.             return pFTH->fn_(t1, t2, t3);
  75.         }
  76.  
  77.     private:
  78.         func_type& func;
  79.     };
  80.  
  81.     template <typename ResType, typename ObjType>
  82.     struct mem_func_call_impl
  83.     {
  84.         mem_func_call_impl(ObjType& obj_, func_type& mem_func_): obj(obj_), mem_func(mem_func_) {}
  85.  
  86.     public:
  87.         ResType operator ()()
  88.         {
  89.             func_type_holder<ResType (ObjType::*)()>* pFTH = dynamic_cast<func_type_holder<ResType (ObjType::*)()>*>(&mem_func);
  90.             if (pFTH == NULL)
  91.                 throw function_type_unmatched("mem_func_call_impl::operator ()()");
  92.             return (obj.*(pFTH->fn_))();
  93.         }
  94.  
  95.         template <typename T1>
  96.         ResType operator ()(T1 t1)
  97.         {
  98.             func_type_holder<ResType (ObjType::*)(T1)>* pFTH = dynamic_cast<func_type_holder<ResType (ObjType::*)(T1)>*>(&mem_func);
  99.             if (pFTH == NULL)
  100.                 throw function_type_unmatched("mem_func_call_impl::operator ()(T1)");
  101.             return (obj.*(pFTH->fn_))(t1);
  102.         }
  103.  
  104.         template <typename T1, typename T2>
  105.         ResType operator ()(T1 t1, T2 t2)
  106.         {
  107.             func_type_holder<ResType (ObjType::*)(T1, T2)>* pFTH = dynamic_cast<func_type_holder<ResType (ObjType::*)(T1, T2)>*>(&mem_func);
  108.             if (pFTH == NULL)
  109.                 throw function_type_unmatched("mem_func_call_impl::operator ()(T1, T2)");
  110.             return (obj.*(pFTH->fn_))(t1, t2);
  111.         }
  112.  
  113.         template <typename T1, typename T2, typename T3>
  114.         ResType operator ()(T1 t1, T2 t2, T3 t3)
  115.         {
  116.             func_type_holder<ResType (ObjType::*)(T1, T2, T3)>* pFTH = dynamic_cast<func_type_holder<ResType (ObjType::*)(T1, T2, T3)>*>(&mem_func);
  117.             if (pFTH == NULL)
  118.                 throw function_type_unmatched("mem_func_call_impl::operator ()(T1, T2, T3)");
  119.             return (obj.*(pFTH->fn_))(t1, t2, t3);
  120.         }
  121.  
  122.     private:
  123.         ObjType& obj;
  124.         func_type& mem_func;
  125.     };
  126.  
  127.     class dynamic_call
  128.     {
  129.         typedef std::map<std::string, func_type*> ContType;
  130.  
  131.     public:
  132.         template <typename FuncType>
  133.         bool regFunc(FuncType pfn, const std::string& fnName) // Return true if succeeded
  134.         {
  135.             return funcs_.insert(std::make_pair(fnName, new func_type_holder<FuncType>(pfn))).second;
  136.         }
  137.  
  138.         bool unregFunc(const std::string& fnName)  // Return true if succeeded
  139.         {
  140.             ContType::iterator it = funcs_.find(fnName);
  141.             if (it == funcs_.end())
  142.                 return false;
  143.             delete it->second;
  144.             funcs_.erase(it);
  145.             return true;
  146.         }
  147.  
  148.         ~dynamic_call()
  149.         {
  150.             for (ContType::iterator it = funcs_.begin(); it != funcs_.end(); ++it)
  151.                 delete it->second;
  152.         }
  153.  
  154.         template <typename ResType>
  155.         func_call_impl<ResType> callFunc(const std::string& fnName)
  156.         {
  157.             ContType::iterator it = funcs_.find(fnName);
  158.             if (it == funcs_.end())
  159.                 throw function_not_found(fnName);
  160.             return func_call_impl<ResType>(*it->second);
  161.         }
  162.  
  163.         template <typename ResType, typename ObjType>
  164.         mem_func_call_impl<ResType, ObjType> callMemFunc(const std::string& fnName, ObjType& obj)
  165.         {
  166.             ContType::iterator it = funcs_.find(fnName);
  167.             if (it == funcs_.end())
  168.                 throw function_not_found(fnName);
  169.             return mem_func_call_impl<ResType, ObjType>(obj, *it->second);
  170.         }
  171.  
  172.     private:
  173.         ContType funcs_;
  174.     };
  175. }
  176. #define REG_FUNC(func) regFunc(func, #func)
  177. #define REG_MEM_FUNC(mem_func) regFunc(&mem_func, #mem_func)
  178.  
  179. void fn()
  180. {
  181.     std::cout << "fn() is called" << std::endl;
  182. }
  183.  
  184. struct A
  185. {
  186.     A(int i_): i(i_) {};
  187.     int fn1(int a)
  188.     {
  189.         std::cout << "A::fn1(" << a << ") is called, with A::i=" << i << std::endl;
  190.         return a + i;
  191.     }
  192.  
  193.     void fn2()
  194.     {
  195.         std::cout << "This should not be displayed" << std::endl;
  196.     }
  197.  
  198.     int i;
  199. };
  200.  
  201. struct B {};
  202.  
  203. int main()
  204. {
  205.     using namespace std;
  206.     dynamic_call::dynamic_call fns;
  207.     fns.REG_MEM_FUNC(A::fn1);
  208.     fns.REG_FUNC(fn);
  209.     fns.REG_MEM_FUNC(A::fn2);
  210.     A a(10);
  211.     B b;
  212.  
  213.     int res = fns.callMemFunc<int>("A::fn1", a)(10);
  214.     cout << "Result of A::fn1 = " << res << endl;
  215.  
  216.     fns.callFunc<void>("fn")();
  217.  
  218.     try {
  219.         fns.callMemFunc<void>("A::fn2", b)(10);
  220.     } catch (exception& e) {
  221.         cout << "Exception catched: " << e.what() << endl;
  222.     }
  223. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement