fork download
  1. #include <algorithm>
  2. #include <functional>
  3. #include <iomanip>
  4. #include <iostream>
  5. #include <memory>
  6. #include <vector>
  7.  
  8. using std::size_t;
  9.  
  10. struct Tested;
  11.  
  12.  
  13. class CallChecker
  14. {
  15. public:
  16. typedef void (Tested::*Call)();
  17.  
  18. template <class T>
  19. struct type_identity { typedef T type; };
  20. template <class T>
  21. using type = typename type_identity<T>::type; //used to prevent deduction
  22.  
  23. template <class R, class... A>
  24. void addCheck(R (Tested::*call)(A...), type<std::function<bool (A...)>> check)
  25. {
  26. auto key = reinterpret_cast<Call>(call);
  27. mChecks.emplace_back(key, std::make_shared<CheckImpl<A...>>(std::move(check)));
  28. }
  29.  
  30. template <class R, class... A>
  31. bool checkCall(R (Tested::*call)(A...), type<A>... arg)
  32. {
  33. auto key = reinterpret_cast<Call>(call);
  34. auto hasKey = [key](const std::pair<Call, std::shared_ptr<Check>> &p)
  35. { return p.first == key; };
  36. for (
  37. auto it = std::find_if(begin(mChecks), end(mChecks), hasKey);
  38. it != end(mChecks);
  39. it = std::find_if(++it, end(mChecks), hasKey)
  40. )
  41. {
  42. auto *check = static_cast<CheckImpl<A...>*>(it->second.get());
  43. if (check->mCheck(arg...))
  44. return true;
  45. }
  46. return false;
  47. }
  48.  
  49. private:
  50. struct Check
  51. {
  52. virtual ~Check() {}
  53. };
  54.  
  55. template <class... A>
  56. struct CheckImpl : Check
  57. {
  58. std::function<bool (A...)> mCheck;
  59.  
  60. CheckImpl(std::function<bool (A...)> check) : mCheck(std::move(check)) {}
  61. };
  62.  
  63. std::vector<std::pair<Call, std::shared_ptr<Check>>> mChecks;
  64. };
  65.  
  66.  
  67. struct Tested : public CallChecker
  68. {
  69. void foo() { std::cout << "foo: " << checkCall(&Tested::foo) << '\n'; }
  70.  
  71. void bar(std::string s, int i) { std::cout << "bar: " << checkCall(&Tested::bar, std::move(s), i) << '\n'; }
  72. };
  73.  
  74. int main() {
  75. std::cout << std::boolalpha;
  76. Tested test;
  77. test.addCheck(&Tested::foo, [] { return true; });
  78. test.foo();
  79. test.bar("adams", 42);
  80. test.addCheck(&Tested::bar, [](std::string s, int i) { return s == "adams" && i == 42; });
  81. test.bar("adams", 42);
  82. test.bar("douglas", 42);
  83. return 0;
  84. }
Success #stdin #stdout 0s 3480KB
stdin
Standard input is empty
stdout
foo: true
bar: false
bar: true
bar: false