Advertisement
Guest User

Untitled

a guest
Jun 19th, 2019
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.79 KB | None | 0 0
  1. // main.cpp
  2. #include <iostream>
  3. #include <unordered_map>
  4. #include <functional>
  5. #include <typeinfo>
  6. #include <typeindex>
  7. #include <type_traits>
  8. #include "function_traits.h"
  9.  
  10. class Event
  11. {
  12. public:
  13. virtual ~Event()
  14. {}
  15. protected:
  16. Event() = default;
  17. };
  18.  
  19. class TestEvent : public Event
  20. {};
  21.  
  22. class EventDispatcher
  23. {
  24. public:
  25. template<class F>
  26. void Register( F&& f )
  27. {
  28. // this static assert seems to always fail
  29. //static_assert(std::is_invocable<F>::value,"Handler must be invocable.");
  30. using Traits = function_traits<F>;
  31. static_assert(Traits::arity == 1,"Handler must have exactly 1 parameter.");
  32. using PCRef = typename Traits::template argument<0>::type;
  33. using PC = typename std::remove_reference<PCRef>::type;
  34. using P = typename std::remove_const<PC>::type;
  35. static_assert(std::is_base_of<Event,P>::value && !std::is_same<Event,P>::value,"Handler parameter must be derived from Event.");
  36. static_assert(std::is_reference<PCRef>::value,"Handler parameter must be passed by reference.");
  37. static_assert(std::is_const<PC>::value,"Handler parameter must be constant reference.");
  38.  
  39. // wrap f in a lambda that casts to specific event handled
  40. handlers[typeid(P)] = [f]( const Event& e )
  41. {
  42. f( static_cast<const P&>(e) );
  43. };
  44. }
  45. void Dispatch( const Event& e ) const
  46. {
  47. auto i = handlers.find( typeid(e) );
  48. if( i != handlers.end() )
  49. {
  50. i->second( e );
  51. }
  52. }
  53. private:
  54. std::unordered_map<std::type_index,std::function<void(const Event&)>> handlers;
  55. };
  56.  
  57. void FreeFunctionHandler( [[maybe_unused]] const TestEvent& e )
  58. {
  59. std::cout << "TestEvent fired; handled by free function." << std::endl;
  60. }
  61.  
  62. int main()
  63. {
  64. constexpr bool using_lambda = true;
  65. EventDispatcher ed;
  66.  
  67. if constexpr( using_lambda )
  68. {
  69. ed.Register([]( [[maybe_unused]] const TestEvent& e )
  70. {
  71. std::cout << "TestEvent fired; handled by lambda function." << std::endl;
  72. });
  73. }
  74. else
  75. {
  76. ed.Register( FreeFunctionHandler );
  77. }
  78.  
  79. ed.Dispatch( TestEvent{} );
  80.  
  81. return 0;
  82. }
  83.  
  84. // function_traits.h
  85. #pragma once
  86. #include <tuple>
  87.  
  88. template<class F>
  89. struct function_traits;
  90.  
  91. // function pointer
  92. template<class R,class... Args>
  93. struct function_traits<R( *)(Args...)> : public function_traits<R( Args... )>
  94. {};
  95.  
  96. template<class R,class... Args>
  97. struct function_traits<R( Args... )>
  98. {
  99. using return_type = R;
  100.  
  101. static constexpr std::size_t arity = sizeof...(Args);
  102.  
  103. template <std::size_t N>
  104. struct argument
  105. {
  106. static_assert(N < arity,"error: invalid parameter index.");
  107. using type = typename std::tuple_element<N,std::tuple<Args...>>::type;
  108. };
  109. };
  110.  
  111. // member function pointer
  112. template<class C, class R, class... Args>
  113. struct function_traits<R(C::*)(Args...)> : public function_traits<R(C&,Args...)>
  114. {};
  115.  
  116. // const member function pointer
  117. template<class C, class R, class... Args>
  118. struct function_traits<R(C::*)(Args...) const> : public function_traits<R(C&,Args...)>
  119. {};
  120.  
  121. // member object pointer
  122. template<class C, class R>
  123. struct function_traits<R(C::*)> : public function_traits<R(C&)>
  124. {};
  125.  
  126. // functor
  127. template<class F>
  128. struct function_traits
  129. {
  130. private:
  131. using call_type = function_traits<decltype(&F::type::operator())>;
  132. public:
  133. using return_type = typename call_type::return_type;
  134.  
  135. static constexpr std::size_t arity = call_type::arity - 1;
  136.  
  137. template <std::size_t N>
  138. struct argument
  139. {
  140. static_assert(N < arity,"error: invalid parameter index.");
  141. using type = typename call_type::template argument<N + 1>::type;
  142. };
  143. };
  144.  
  145. template<class F>
  146. struct function_traits<F&> : public function_traits<F>
  147. {};
  148.  
  149. template<class F>
  150. struct function_traits<F&&> : public function_traits<F>
  151. {};
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement