Guest User

Untitled

a guest
Jan 16th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.51 KB | None | 0 0
  1. #include <functional>
  2. #include <vector>
  3. #include <tuple>
  4.  
  5. template<typename ... Funcs>
  6. class Observable
  7. {
  8. public:
  9. using ObserverList = std::tuple<std::vector<std::function<Funcs>>...>;
  10.  
  11. template<unsigned int eventidx, typename Callable>
  12. void AttachObserver(Callable c)
  13. {
  14. std::get<eventidx>(observers).push_back(c);
  15. }
  16.  
  17. template<unsigned int eventidx, typename ... T>
  18. void NotifyObserversOfEvent(T ... args)
  19. {
  20. for(auto f: std::get<eventidx>(observers))
  21. {
  22. f(std::forward<T>(args)...);
  23. }
  24. }
  25.  
  26. private:
  27. ObserverList observers;
  28. };
  29.  
  30. #include <iostream>
  31. #include <functional>
  32. #include <vector>
  33.  
  34. #include "observable.h"
  35.  
  36. class A : public Observable<
  37. void(void),
  38. void(int,std::string),
  39. void(int,int),
  40. >
  41. {
  42. public:
  43. enum Event : unsigned
  44. {
  45. Event0,
  46. Event1,
  47. Event2
  48. };
  49.  
  50. private:
  51. int a;
  52. std::string s;
  53. };
  54.  
  55. class B
  56. {
  57. public:
  58. void EventZeroHappened()
  59. {
  60. std::cout << "B has observed event zeron";
  61. }
  62.  
  63.  
  64. void EventOneHappened(int a, std::string s)
  65. {
  66. std::cout << "B has observed event one with params: " << a << " and " << """ << s << """ <<'n';
  67. }
  68.  
  69. void EventTwoHappened(int a, int b)
  70. {
  71. std::cout << "B has observed event two with params: " << a << " and " << b <<'n';
  72. }
  73. };
  74.  
  75.  
  76.  
  77.  
  78. int main()
  79. {
  80. A a;
  81. B b;
  82.  
  83. a.AttachObserver<A::Event::Event0>([&b](){b.EventZeroHappened();});
  84. a.AttachObserver<A::Event::Event1>([&b](int i, std::string s){b.EventOneHappened(i,s);});
  85. a.AttachObserver<A::Event::Event2>([&b](int i, int j){b.EventTwoHappened(i,j);});
  86.  
  87. a.NotifyObserversOfEvent<A::Event::Event0>();
  88. a.NotifyObserversOfEvent<A::Event::Event1>(37,"Hello There");
  89. a.NotifyObserversOfEvent<A::Event::Event2>(182,150);
  90. }
  91.  
  92. class PolymorphicBehavior {
  93. class Concept {
  94. // here are the virtual functions
  95. };
  96. template <typename ConcreteType>
  97. class Object {
  98. // here are concrete implementations of the functions
  99. // The class encapsulates type information
  100. private:
  101. ConcreteType value;
  102. };
  103. public:
  104. template <typename ConcreteType>
  105. PolymorphicBehavior(const ConcreteType& ct) : ptr(new Object<ConcreteType>(ct)) {}
  106. private:
  107. Concept* ptr;
  108. };
  109.  
  110. #include <iostream>
  111. #include <vector>
  112. #include <memory>
  113. #include <tuple>
  114. #include <any>
  115. #include <functional>
  116.  
  117. //deducing the tuple type from the function type
  118. // e.g: std::function<void(float, double)> => std::tuple<float, double>
  119. template <typename T>
  120. struct tuple_desc;
  121. template <typename R, typename... Args>
  122. struct tuple_desc<std::function<R(Args...)>> {
  123. using type = std::tuple<Args...>;
  124. };
  125.  
  126. // deducing the function signature from the callable
  127. template <typename Callable>
  128. using function_class = decltype(std::function(std::declval<Callable>()));
  129.  
  130. class Observable {
  131.  
  132. class Observable_model { // type neutral hook
  133. public:
  134. virtual void notify(unsigned event_number, std::any& argument_wrapper) = 0;
  135. virtual ~Observable_model() = default;
  136. };
  137.  
  138. template <typename Callback>
  139. class Observable_object : public Observable_model { // stores concrete type information
  140. public:
  141. Observable_object(unsigned event_class, const Callback& cbk) : event_class(event_class), callback(cbk) {}
  142.  
  143. void notify(unsigned event_number, std::any& argument_wrapper) override {
  144. using Arg_tuple = typename tuple_desc<decltype(this->callback)>::type; // so tuple<int, float> for [](int a, float b) { /*...*/ }
  145. if (event_number == event_class) { // dynamic dispatch
  146. std::apply(callback, std::any_cast<Arg_tuple> (argument_wrapper));
  147. }
  148. }
  149. private:
  150. unsigned event_class;
  151. function_class<Callback> callback;
  152. };
  153.  
  154. public:
  155. template <typename Callback>
  156. void attach(unsigned event_class, Callback&& callback) {
  157. auto new_obj = std::make_unique<Observable_object<Callback>>(event_class, callback);
  158. observations.push_back(std::move(new_obj));
  159. }
  160. template <typename... Args>
  161. void notify(unsigned event_number, Args&&... args) {
  162. std::tuple<Args...> arg_tuple(std::forward<Args>(args)...);
  163. std::any argument_wrapper(arg_tuple); // argument type erasure
  164. for (auto& obs : observations) obs->notify(event_number, argument_wrapper);
  165. }
  166.  
  167. private:
  168. std::vector<std::unique_ptr<Observable_model>> observations;
  169.  
  170. };
  171.  
  172. // testing the interface;
  173.  
  174. enum { WILDLIFE = 0, MACHINES = 1 };
  175.  
  176. struct Buzzer {
  177. void go(int h) { std::cout << "drrrr... drrrr... it's " << h << " a.m, time to wake up!n"; }
  178. };
  179. struct Coffee_machine {
  180. void make_coffee(int h) { if (h == 7) std::cout << "time to make coffee!n"; else std::cout << "no coffee yet baby!n"; }
  181. };
  182.  
  183. struct Rooster {
  184. void sing() { std::cout << "Cocorico!n"; }
  185. };
  186. struct Vampire {
  187. void bury() { std::cout << "Bye! I'll be in my grave!n"; }
  188. };
  189.  
  190. struct Sun : public Observable {
  191. void rise() {
  192. std::cout << "Waouh, the sun rises!n";
  193. notify(0);
  194. notify(1, 6);
  195. }
  196. };
  197.  
  198. int main() {
  199. Sun sun;
  200. Buzzer buzzer;
  201. Rooster rooster;
  202. Vampire vampire;
  203. Coffee_machine coffee_machine;
  204. sun.attach(WILDLIFE, [&rooster] {rooster.sing();});
  205. sun.attach(WILDLIFE, [&vampire] {vampire.bury();});
  206. sun.attach(MACHINES, [&buzzer](int h) {buzzer.go(h);});
  207. sun.attach(MACHINES, [&coffee_machine](int h) {coffee_machine.make_coffee(h);});
  208. sun.rise();
  209. }
Add Comment
Please, Sign In to add comment