fork(1) download
  1. #include <iostream>
  2. #include <type_traits>
  3. #include <functional>
  4.  
  5.  
  6. template <typename T>
  7. using GetBaseType = typename T::Base;
  8. using NoBase = void;
  9.  
  10. template <typename T>
  11. class CallUp;
  12.  
  13. template <>
  14. class CallUp<NoBase>
  15. {
  16. public:
  17. template <typename Op, typename T>
  18. CallUp(Op&& ignoreOperation, T&& ignoreObject) {}
  19. };
  20.  
  21.  
  22. template <typename T>
  23. class CallUp : public CallUp<GetBaseType<T>>
  24. {
  25. public:
  26. template <typename Op>
  27. CallUp(Op&& op, T& obj) : CallUp<GetBaseType<T>>(op, obj), op(std::forward<Op>(op)), obj(obj)
  28. {}
  29. ~CallUp()
  30. {
  31. op(obj);
  32. }
  33. private:
  34. std::function<void(T&)> op;
  35. T& obj;
  36. };
  37.  
  38. template <typename T>
  39. class ConstCallUp;
  40.  
  41. template <>
  42. class ConstCallUp<NoBase>
  43. {
  44. public:
  45. template <typename Op, typename T>
  46. ConstCallUp(Op&& ignoreOperation, T&& ignoreObject) {}
  47. };
  48.  
  49. template <typename T>
  50. class ConstCallUp : public ConstCallUp<GetBaseType<T>>
  51. {
  52. public:
  53. template <typename Op>
  54. ConstCallUp(Op&& op, const T& obj) : ConstCallUp<GetBaseType<T>>(op, obj), op(std::forward<Op>(op)), obj(obj)
  55. {}
  56. ~ConstCallUp()
  57. {
  58. op(obj);
  59. }
  60. private:
  61. std::function<void(T&)> op;
  62. const T& obj;
  63. };
  64.  
  65. template <typename Op, typename T>
  66. auto callUp(Op&& op, T& obj)
  67. {
  68. return CallUp<T>(std::forward<Op>(op), obj);
  69. }
  70. template <typename Op, typename T>
  71. auto callUp(Op&& op, const T& obj)
  72. {
  73. return ConstCallUp<T>(std::forward<Op>(op), obj);
  74. }
  75.  
  76. class Foo0
  77. {
  78. public:
  79. using Base = NoBase;
  80. void reset()
  81. {
  82. std::cout << "reset Foo0\n";
  83. }
  84. void print() const
  85. {
  86. std::cout << "Foo0\n";
  87. }
  88. };
  89.  
  90. class Foo1 : public Foo0
  91. {
  92. public:
  93. using Base = Foo0;
  94. void reset()
  95. {
  96. std::cout << "reset Foo1\n";
  97. }
  98. void print() const
  99. {
  100. std::cout << "Foo1\n";
  101. }
  102. };
  103.  
  104. class Foo2 : public Foo1
  105. {
  106. public:
  107. using Base = Foo1;
  108. void reset()
  109. {
  110. std::cout << "reset Foo2\n";
  111. }
  112. void print() const
  113. {
  114. std::cout << "Foo2\n";
  115. }
  116. };
  117.  
  118.  
  119. int main() {
  120. Foo2 foo2;
  121. callUp([](auto&& obj){obj.reset();}, foo2);
  122. callUp([](auto&& obj){obj.print();}, foo2);
  123. }
Success #stdin #stdout 0s 3412KB
stdin
Standard input is empty
stdout
reset Foo2
reset Foo1
reset Foo0
Foo2
Foo1
Foo0