fork download
  1. #include <iostream>
  2. #include <cstring>
  3.  
  4. template<typename ReturnType, typename... ParameterTypes>
  5. class IDelegateBinding
  6. {
  7. public:
  8.  
  9. virtual ReturnType Execute(void* Object, ParameterTypes... Parameters) = 0;
  10. };
  11.  
  12. template<typename ObjectType, typename ReturnType, typename... ParameterTypes>
  13. class FDelegateBinding : public IDelegateBinding<ReturnType, ParameterTypes...>
  14. {
  15. using MethodType = ReturnType (ObjectType::*)(ParameterTypes...);
  16.  
  17. MethodType BoundMethod;
  18.  
  19. public:
  20.  
  21. FDelegateBinding(MethodType Method)
  22. : BoundMethod(Method)
  23. {
  24. }
  25.  
  26. virtual ReturnType Execute(void* Object, ParameterTypes... Parameters) override
  27. {
  28. return (((ObjectType*)Object)->*BoundMethod)(Parameters...);
  29. }
  30. };
  31.  
  32. template<typename ReturnType, typename... ParameterTypes>
  33. class FDelegate
  34. {
  35. using DummyDelegateBinding = FDelegateBinding<class FDummyClass, ReturnType, ParameterTypes...>;
  36.  
  37. typename std::aligned_storage<sizeof(DummyDelegateBinding), alignof(DummyDelegateBinding)>::type Binding;
  38.  
  39. public:
  40.  
  41. FDelegate()
  42. {
  43. std::memset(&Binding, 0, sizeof(Binding));
  44. }
  45.  
  46. template<typename ClassName>
  47. void Bind(ReturnType (ClassName::*Method)(ParameterTypes...))
  48. {
  49. new (&Binding) FDelegateBinding<ClassName, ReturnType, ParameterTypes...>(Method);
  50. }
  51.  
  52. void Unbind()
  53. {
  54. std::memset(Binding, 0, sizeof(Binding));
  55. }
  56.  
  57. bool IsBound() const
  58. {
  59. return (void*&)Binding != nullptr;
  60. }
  61.  
  62. template<typename ObjectType>
  63. ReturnType Execute(ObjectType* Object, ParameterTypes... Parameters)
  64. {
  65. return ((IDelegateBinding<ReturnType, ParameterTypes...>&)Binding).Execute(Object, Parameters...);
  66. }
  67.  
  68. template<typename ObjectType>
  69. ReturnType ExecuteIfBound(ObjectType* Object, ParameterTypes... Parameters)
  70. {
  71. if (IsBound())
  72. {
  73. return Execute<ObjectType>(Object, Parameters...);
  74. }
  75. }
  76. };
  77.  
  78. class FSampleBase
  79. {
  80. protected:
  81.  
  82. FDelegate<void, int> NotifyFooInvoked;
  83.  
  84. public:
  85.  
  86. void Foo(int Value)
  87. {
  88. NotifyFooInvoked.ExecuteIfBound(this, Value);
  89. }
  90. };
  91.  
  92. class FSampleDerived : public FSampleBase
  93. {
  94. int SampleData;
  95.  
  96. public:
  97.  
  98. FSampleDerived(int Data)
  99. : SampleData(Data)
  100. {
  101. NotifyFooInvoked.Bind(&FSampleDerived::OnFooInvoked);
  102. }
  103.  
  104. void OnFooInvoked(int Value)
  105. {
  106. std::cout << "Foo Invoked: " << Value << " [Sample Data: " << SampleData << "]" << std::endl;
  107. }
  108. };
  109.  
  110. int main()
  111. {
  112. FSampleDerived FirstSample(11);
  113. FSampleDerived* SecondSample = (FSampleDerived*)std::malloc(sizeof(FSampleDerived));
  114.  
  115. std::memcpy(SecondSample, &FirstSample, sizeof(FSampleDerived));
  116.  
  117. FirstSample.Foo(1);
  118. SecondSample->Foo(2);
  119.  
  120. std::free(SecondSample);
  121.  
  122. return 0;
  123. }
Success #stdin #stdout 0s 4476KB
stdin
Standard input is empty
stdout
Foo Invoked: 1 [Sample Data: 11]
Foo Invoked: 2 [Sample Data: 11]