Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- using namespace std;
- typedef void (*CallerFunction)(void*);
- // macro for determining array size in compile time
- template <typename T, size_t N>
- char (&ArraySizeHelper(T (&array)[N]))[N];
- struct Binding
- {
- Binding(const char *funName, CallerFunction fun) :
- functionName(funName),
- function(fun)
- {
- }
- const char *functionName;
- const CallerFunction function;
- };
- template<class T>
- class Wrapper
- {
- public:
- static void registerWrapper()
- {
- cout << "Registering " << s_Name << ". Functions: ";
- for (int i = 0; i < s_BindingsLength; ++i) {
- cout << s_Bindings[i].functionName << ", ";
- /* ... do something else ... */
- }
- cout << endl;
- }
- static void call(T &obj, const string &funName)
- {
- for (int i = 0; i < s_BindingsLength; ++i) {
- if (!funName.compare(s_Bindings[i].functionName)) {
- s_Bindings[i].function(&obj);
- return;
- }
- }
- }
- protected:
- typedef void (T::*MemberFunctionPtr)();
- template<MemberFunctionPtr ptr> static void caller(void *inst)
- {
- (((T*)inst)->*ptr)();
- }
- template<void (*ptr)()> static void caller(void *inst)
- {
- ptr();
- }
- // must be defined in child classes
- static const string &s_Name;
- static const Binding s_Bindings[];
- static const int s_BindingsLength;
- };
- // macros for saving time
- #define BIND_START(Class) \
- namespace _Bind##Class##Namespace { \
- typedef Class _BindClass; \
- template<> const string &Wrapper<_BindClass>::s_Name = #Class; \
- template<> const Binding Wrapper<_BindClass>::s_Bindings[] = {
- #define BIND(FunctionName, Function) \
- Binding(FunctionName, &caller<Function>),
- #define BIND_END \
- };\
- template<> const int Wrapper<_BindClass>::s_BindingsLength = \
- (sizeof(ArraySizeHelper(s_Bindings))); \
- }
- // child classes
- class Foo : public Wrapper<Foo>
- {
- public:
- void f1() { cout << "I'm Foo::f1!" << endl; }
- void f2() { cout << "I'm Foo::f2!" << endl; }
- };
- class Bar : public Wrapper<Bar>
- {
- public:
- void f1() { cout << "I'm Bar::f1!" << endl; }
- void f2() { cout << "I'm Bar::f2!" << endl; }
- };
- // non-member functions can be used too
- void outer() { cout << "Hey, im outer function!" << endl; }
- // bindings
- BIND_START(Foo)
- BIND("m1", &Foo::f1)
- BIND("m2", &Foo::f2)
- BIND("m3", &Foo::f1)
- BIND("outer", &outer)
- BIND_END
- BIND_START(Bar)
- BIND("m1", &Bar::f1)
- BIND("m2", &Bar::f2)
- BIND("outer", &outer)
- BIND_END
- // same without macroses
- /*
- template<> const string &Wrapper<Foo>::s_Name = "Foo";
- template<> const Binding Wrapper<Foo>::s_Bindings[] = {
- Binding("m1", &caller<&Foo::f1>),
- Binding("m2", &caller<&Foo::f2>),
- Binding("m3", &caller<&Foo::f1>),
- Binding("outer", &caller<&outer>),
- };
- template<> const int Wrapper<Foo>::s_BindingsLength =
- (sizeof(ArraySizeHelper(s_Bindings)));
- template<> const string &Wrapper<Bar>::s_Name = "Bar";
- template<> const Binding Wrapper<Bar>::s_Bindings[] = {
- Binding("m1", &caller<&Bar::f1>),
- Binding("m2", &caller<&Bar::f2>),
- Binding("outer", &caller<&outer>),
- };
- template<> const int Wrapper<Bar>::s_BindingsLength =
- (sizeof(ArraySizeHelper(s_Bindings)));
- */
- int main()
- {
- Foo::registerWrapper();
- Foo a;
- Foo::call(a, "m1");
- Foo::call(a, "m2");
- Foo::call(a, "m3");
- Foo::call(a, "outer");
- Bar::registerWrapper();
- Bar b;
- Bar::call(b, "m1");
- Bar::call(b, "m2");
- Bar::call(b, "outer");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement