fork download
  1. #include <list>
  2. #include <iostream>
  3.  
  4. /* Class to be used as a member of the delegation host.
  5.   Keeps a list of event clients, which you can iterate over.
  6.   As a C++11 convenience, function call operator() is overloaded to call
  7.   all clients with the given argument list.
  8.  
  9.   This is templated over the base type for the clients. The base type
  10.   should define virtual function(s) for handling the events.
  11.   Templating is necessary because we can't anticipate the number or types
  12.   of these virtual functions. */
  13.  
  14. template< typename delegate >
  15. struct delegator {
  16. typedef std::list< delegate * > list; // host interface
  17. list delegates;
  18.  
  19. typedef typename list::iterator delegate_id; // client interface
  20.  
  21. delegate_id add( delegate *d )
  22. { return delegates.insert( delegates.end(), d ); }
  23.  
  24. void remove( delegate_id d )
  25. { delegates.erase( d ); }
  26.  
  27. #if __cplusplus >= 201103L // C++11-only convenient host interface
  28. template< typename ... args >
  29. void operator() ( args && ... a ) {
  30. for ( auto d : delegates ) ( *d )( std::forward< args >( a ) ... );
  31. }
  32. #endif
  33. };
  34.  
  35. /* Abstract base class for all delegate bases. Registers and unregisters
  36.   from the delegator, but doesn't define any event handler. */
  37. template< typename derived >
  38. struct delegate {
  39. typedef ::delegator< derived > delegator;
  40.  
  41. delegator &source;
  42. typename delegator::delegate_id id;
  43.  
  44. delegate( delegator &in_source )
  45. : source( in_source ),
  46. id( source.add( static_cast< derived * >( this ) ) ) {}
  47.  
  48. virtual ~delegate() { source.remove( id ); }
  49. };
  50.  
  51. /* Example delegate base. Defines an event handler which clients must implement.
  52.   Other types of events might declare other bases. */
  53. struct my_delegate_base : delegate< my_delegate_base > {
  54. typedef delegate< my_delegate_base > base;
  55. typedef base::delegator delegator;
  56. my_delegate_base( delegator &d ) : base( d ) {}
  57.  
  58. virtual void operator() ( int ) = 0;
  59. };
  60.  
  61. /* Example client class defines how to handle an event. */
  62. struct my_delegate_impl : my_delegate_base {
  63. my_delegate_impl( delegator &d ) : my_delegate_base( d ) {}
  64.  
  65. virtual void operator() ( int i ) {
  66. std::cout << i << '\n';
  67. }
  68. };
  69. struct my_delegate_impl2 : my_delegate_base {
  70. my_delegate_impl2( delegator &d ) : my_delegate_base( d ) {}
  71.  
  72. virtual void operator() ( int i ) {
  73. std::cout << - i << '\n';
  74. }
  75. };
  76.  
  77. int main() {
  78. typedef delegator< my_delegate_base > my_delegator;
  79. my_delegator distro;
  80. my_delegate_impl a( distro ), b( distro );
  81. my_delegate_impl2 c( distro );
  82.  
  83. for ( my_delegator::delegate_id d = distro.delegates.begin();
  84. d != distro.delegates.end(); ++ d ) {
  85. ( **d )( 5 );
  86. }
  87. }
  88.  
Success #stdin #stdout 0.01s 2860KB
stdin
Standard input is empty
stdout
5
5
-5