Advertisement
Zhur

Template magic

Jan 26th, 2013
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.69 KB | None | 0 0
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. typedef void (*CallerFunction)(void*);
  6.  
  7. // macro for determining array size in compile time
  8. template <typename T, size_t N>
  9. char (&ArraySizeHelper(T (&array)[N]))[N];
  10.  
  11. struct Binding
  12. {
  13.     Binding(const char *funName, CallerFunction fun) :
  14.         functionName(funName),
  15.         function(fun)
  16.     {
  17.     }
  18.  
  19.     const char *functionName;
  20.     const CallerFunction function;
  21. };
  22.  
  23. template<class T>
  24. class Wrapper
  25. {
  26. public:
  27.     static void registerWrapper()
  28.     {
  29.         cout << "Registering " << s_Name << ". Functions: ";
  30.  
  31.         for (int i = 0; i < s_BindingsLength; ++i) {
  32.             cout << s_Bindings[i].functionName << ", ";
  33.             /* ... do something else ... */
  34.         }
  35.         cout << endl;
  36.     }
  37.  
  38.     static void call(T &obj, const string &funName)
  39.     {
  40.         for (int i = 0; i < s_BindingsLength; ++i) {
  41.             if (!funName.compare(s_Bindings[i].functionName)) {
  42.                 s_Bindings[i].function(&obj);
  43.                 return;
  44.             }
  45.         }
  46.     }
  47.  
  48. protected:
  49.     typedef void (T::*MemberFunctionPtr)();
  50.  
  51.     template<MemberFunctionPtr ptr> static void caller(void *inst)
  52.     {
  53.         (((T*)inst)->*ptr)();
  54.     }
  55.  
  56.     template<void (*ptr)()> static void caller(void *inst)
  57.     {
  58.         ptr();
  59.     }
  60.  
  61.     // must be defined in child classes
  62.     static const string &s_Name;
  63.     static const Binding s_Bindings[];
  64.     static const int s_BindingsLength;
  65. };
  66.  
  67. // macros for saving time
  68.  
  69. #define BIND_START(Class) \
  70.     namespace _Bind##Class##Namespace { \
  71.         typedef Class _BindClass; \
  72.         template<> const string &Wrapper<_BindClass>::s_Name = #Class; \
  73.         template<> const Binding Wrapper<_BindClass>::s_Bindings[] = {
  74.  
  75. #define BIND(FunctionName, Function) \
  76.             Binding(FunctionName, &caller<Function>),
  77.  
  78. #define BIND_END \
  79.         };\
  80.         template<> const int Wrapper<_BindClass>::s_BindingsLength = \
  81.             (sizeof(ArraySizeHelper(s_Bindings))); \
  82.     }
  83.  
  84. // child classes
  85.  
  86. class Foo : public Wrapper<Foo>
  87. {
  88. public:
  89.     void f1() { cout << "I'm Foo::f1!" << endl; }
  90.     void f2() { cout << "I'm Foo::f2!" << endl; }
  91. };
  92.  
  93. class Bar : public Wrapper<Bar>
  94. {
  95. public:
  96.     void f1() { cout << "I'm Bar::f1!" << endl; }
  97.     void f2() { cout << "I'm Bar::f2!" << endl; }
  98. };
  99.  
  100. // non-member functions can be used too
  101.  
  102. void outer() { cout << "Hey, im outer function!" << endl; }
  103.  
  104. // bindings
  105.  
  106. BIND_START(Foo)
  107.     BIND("m1", &Foo::f1)
  108.     BIND("m2", &Foo::f2)
  109.     BIND("m3", &Foo::f1)
  110.     BIND("outer", &outer)
  111. BIND_END
  112.  
  113. BIND_START(Bar)
  114.     BIND("m1", &Bar::f1)
  115.     BIND("m2", &Bar::f2)
  116.     BIND("outer", &outer)
  117. BIND_END
  118.  
  119. // same without macroses
  120. /*
  121. template<> const string &Wrapper<Foo>::s_Name = "Foo";
  122. template<> const Binding Wrapper<Foo>::s_Bindings[] = {
  123.     Binding("m1", &caller<&Foo::f1>),
  124.     Binding("m2", &caller<&Foo::f2>),
  125.     Binding("m3", &caller<&Foo::f1>),
  126.     Binding("outer", &caller<&outer>),
  127. };
  128. template<> const int Wrapper<Foo>::s_BindingsLength =
  129.     (sizeof(ArraySizeHelper(s_Bindings)));
  130.  
  131. template<> const string &Wrapper<Bar>::s_Name = "Bar";
  132. template<> const Binding Wrapper<Bar>::s_Bindings[] = {
  133.     Binding("m1", &caller<&Bar::f1>),
  134.     Binding("m2", &caller<&Bar::f2>),
  135.     Binding("outer", &caller<&outer>),
  136. };
  137. template<> const int Wrapper<Bar>::s_BindingsLength =
  138.     (sizeof(ArraySizeHelper(s_Bindings)));
  139. */
  140.  
  141. int main()
  142. {
  143.     Foo::registerWrapper();
  144.  
  145.     Foo a;
  146.  
  147.     Foo::call(a, "m1");
  148.     Foo::call(a, "m2");
  149.     Foo::call(a, "m3");
  150.     Foo::call(a, "outer");
  151.  
  152.     Bar::registerWrapper();
  153.  
  154.     Bar b;
  155.  
  156.     Bar::call(b, "m1");
  157.     Bar::call(b, "m2");
  158.     Bar::call(b, "outer");
  159. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement