Advertisement
AI_UBI

C++ Delegate Example from habrahabr.ru

Jun 11th, 2016
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.73 KB | None | 0 0
  1. #include <assert.h>
  2.  
  3. //  Контейнер для хранения до 2-х аргументов.
  4. struct NIL {};
  5.  
  6. class IArguments
  7. {
  8. public:
  9.     virtual ~IArguments() {}
  10. };
  11.  
  12. template< class T1 = NIL, class T2 = NIL >
  13. class Arguments : public IArguments
  14. {
  15. public:
  16.    
  17.     T1 arg1; T2 arg2;
  18.  
  19.     Arguments() {}
  20.     Arguments(T1 i_arg1) : arg1(i_arg1) {}
  21.     Arguments(T1 i_arg1, T2 i_arg2) : arg1(i_arg1), arg2(i_arg2) {}
  22.    
  23. };
  24.  
  25. //  Контейнер для хранения указателя на метод.
  26. class IContainer
  27. {
  28. public:
  29.     virtual void Call(IArguments*) = 0;
  30. };
  31.  
  32. template< class T, class M >
  33. class Container : public IContainer
  34. {
  35. };
  36.  
  37. template< class T >
  38. class Container< T, void (T::*)(void) > : public IContainer
  39. {
  40.     typedef void (T::*M)(void);
  41.     T* m_class; M m_method;
  42.  
  43. public:
  44.  
  45.     Container(T* c, M m) : m_class(c), m_method(m) {}
  46.  
  47.     void Call(IArguments* i_args)
  48.     {
  49.         (m_class->*m_method)();
  50.     }
  51. };
  52.  
  53. //  Специализация для метода с одним аргументом.
  54. template< class T, class A1 >
  55. class Container< T, void (T::*)(A1) > : public IContainer
  56. {
  57.     typedef void (T::*M)(A1);
  58.     typedef Arguments<A1> A;
  59.     T* m_class; M m_method;
  60.  
  61. public:
  62.  
  63.     Container(T* c, M m) : m_class(c), m_method(m) {}
  64.  
  65.     void Call(IArguments* i_args)
  66.     {
  67.         A* a = dynamic_cast< A* >(i_args);
  68.         assert(a);
  69.         if (a) (m_class->*m_method)(a->arg1);
  70.     }
  71. };
  72.  
  73. template< class T, class A1, class A2 >
  74. class Container< T, void (T::*)(A1, A2) > : public IContainer
  75. {
  76.     typedef void (T::*M)(A1, A2);
  77.     typedef Arguments<A1, A2> A;
  78.     T* m_class; M m_method;
  79.  
  80. public:
  81.    
  82.     Container(T* c, M m) : m_class(c), m_method(m) {}
  83.  
  84.     void Call(IArguments* i_args)
  85.     {
  86.         A* a = dynamic_cast< A* >(i_args);
  87.         assert(a);
  88.         if (a) (m_class->*m_method)(a->arg1, a->arg2);
  89.     }
  90. };
  91.  
  92. class Delegate
  93. {
  94. public:
  95.  
  96.     Delegate() : m_container(0) {}
  97.     ~Delegate() { if (m_container) delete m_container; }
  98.  
  99.     template< class T, class U > void Connect(T* i_class, U i_method)
  100.     {
  101.         if (m_container) delete m_container;
  102.         m_container = new Container< T, U >(i_class, i_method);
  103.     }
  104.  
  105.     void operator()()
  106.     {
  107.         m_container->Call(&Arguments<>());
  108.     }
  109.  
  110.     template< class T1 > void operator()(T1 i_arg1)
  111.     {
  112.         m_container->Call(&Arguments< T1 >(i_arg1));
  113.     }
  114.  
  115.     template< class T1, class T2 > void operator()(T1 i_arg1, T2 i_arg2)
  116.     {
  117.         m_container->Call(&Arguments< T1, T2 >(i_arg1, i_arg2));
  118.     }
  119.  
  120. private:
  121.  
  122.     IContainer* m_container;
  123. };
  124.  
  125. class Victim
  126. {
  127. public:
  128.     void Foo() {}
  129.     void Bar(int) {}
  130. };
  131.  
  132. int main()
  133. {
  134.     Victim test_class;
  135.     Delegate test_delegate;
  136.     test_delegate.Connect(&test_class, &Victim::Foo);
  137.     test_delegate();
  138.     test_delegate.Connect(&test_class, &Victim::Bar);
  139.     test_delegate(10);
  140.  
  141.     return 0;
  142. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement