fork(1) download
  1. #include <memory>
  2. #include <iostream>
  3. #include <functional>
  4.  
  5. template<class... Args>
  6. class DelegateTemplate;
  7.  
  8. class Delegate
  9. {
  10. std::unique_ptr<Delegate> mPtr;
  11. public:
  12. virtual ~Delegate() { }
  13.  
  14. template<class R, class T, class... Args>
  15. void RegisterFunction(R(*target)(Args...), T(*callback)(R), Args... args)
  16. {
  17. mPtr.reset(new DelegateTemplate<R(Args...), T(R)>(target, callback, args...));
  18. }
  19.  
  20. template<class R, class S, class T, class... Args>
  21. void RegisterFunction(R(S::*target)(Args...), S* obj, T(*callback)(R), Args... args)
  22. {
  23. mPtr.reset(new DelegateTemplate<R(Args...), T(R)>(target, obj, callback, args...));
  24. }
  25.  
  26. virtual void CallFunction()
  27. {
  28. mPtr->CallFunction();
  29. }
  30. };
  31.  
  32. template<class R, class T, class... Args>
  33. class DelegateTemplate<R(Args...), T(R)> : public Delegate
  34. {
  35. std::function<R()> mTarget;
  36. std::function<T(R)> mCallback;
  37. public:
  38. DelegateTemplate(R(*target)(Args...), T(*callback)(R), Args... args)
  39. : mTarget(std::bind(target, args...))
  40. , mCallback(callback)
  41. {
  42. }
  43.  
  44. template<class S>
  45. DelegateTemplate(R(S::*target)(Args...), S* obj, T(*callback)(R), Args... args)
  46. : mTarget(std::bind(target, obj, args...))
  47. , mCallback(callback)
  48. {
  49. }
  50.  
  51. ~DelegateTemplate() { }
  52.  
  53. void CallFunction() override
  54. {
  55. mCallback(mTarget());
  56. }
  57. };
  58.  
  59. int Foo1(int i)
  60. {
  61. std::cout << "Foo1.i = " << i << std::endl;
  62. return i;
  63. }
  64.  
  65. void Callback1(int i)
  66. {
  67. std::cout << "Callback1.i = " << i << std::endl;
  68. }
  69.  
  70. const char* Foo2(double r)
  71. {
  72. std::cout << "Foo2.r = " << r << std::endl;
  73. return "hello world";
  74. }
  75.  
  76. void Callback2(const char* str)
  77. {
  78. std::cout << "Callback1.str = " << str << std::endl;
  79. }
  80.  
  81. class Test
  82. {
  83. public:
  84. int Foo3(const char* str)
  85. {
  86. std::cout << "Test::Foo3.str = " << str << std::endl;
  87. return 4;
  88. }
  89. };
  90.  
  91.  
  92. int RefFoo(int &value) {
  93. std::cout << "RefFoo.value = " << value << std::endl;
  94. ++value;
  95. return value;
  96. }
  97.  
  98.  
  99. int main()
  100. {
  101. int source_value_for_direct_call = 5;
  102. std::cout << "source_value_for_direct_call before direct call = " <<
  103. source_value_for_direct_call << std::endl;
  104. RefFoo(source_value_for_direct_call);
  105. std::cout << "source_value_for_direct_call after direct call = " <<
  106. source_value_for_direct_call << std::endl;
  107.  
  108. int source_value_for_delegate_call = 5;
  109. Delegate d;
  110. d.RegisterFunction(&RefFoo,&Callback1, source_value_for_delegate_call);
  111.  
  112. std::cout << "source_value_for_delegate_call before delegate call = " <<
  113. source_value_for_delegate_call << std::endl;
  114. d.CallFunction();
  115. std::cout << "source_value_for_delegate_call after delegate call = " <<
  116. source_value_for_delegate_call << std::endl;
  117. }
  118.  
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp: In function ‘int main()’:
prog.cpp:110:71: error: no matching function for call to ‘Delegate::RegisterFunction(int (*)(int&), void (*)(int), int&)’
  d.RegisterFunction(&RefFoo,&Callback1, source_value_for_delegate_call);
                                                                       ^
prog.cpp:110:71: note: candidates are:
prog.cpp:15:10: note: template<class R, class T, class ... Args> void Delegate::RegisterFunction(R (*)(Args ...), T (*)(R), Args ...)
     void RegisterFunction(R(*target)(Args...), T(*callback)(R), Args... args)
          ^
prog.cpp:15:10: note:   template argument deduction/substitution failed:
prog.cpp:110:71: note:   inconsistent parameter pack deduction with ‘int&’ and ‘int’
  d.RegisterFunction(&RefFoo,&Callback1, source_value_for_delegate_call);
                                                                       ^
prog.cpp:21:10: note: template<class R, class S, class T, class ... Args> void Delegate::RegisterFunction(R (S::*)(Args ...), S*, T (*)(R), Args ...)
     void RegisterFunction(R(S::*target)(Args...), S* obj, T(*callback)(R), Args... args)
          ^
prog.cpp:21:10: note:   template argument deduction/substitution failed:
prog.cpp:110:71: note:   mismatched types ‘R (S::*)(Args ...)’ and ‘int (*)(int&)’
  d.RegisterFunction(&RefFoo,&Callback1, source_value_for_delegate_call);
                                                                       ^
stdout
Standard output is empty