fork(4) download
  1. #include <iostream>
  2. #include <type_traits>
  3. #include <functional>
  4.  
  5.  
  6. template <typename T>
  7. using GetBaseType = typename T::Base;
  8.  
  9. using NoBase = void;
  10.  
  11. template <typename T>
  12. class CallUp;
  13.  
  14. template <>
  15. class CallUp<NoBase>
  16. {
  17. public:
  18. template <typename Op, typename T>
  19. CallUp(Op&& ignoreOperation, T&& ignoreObject) {}
  20. };
  21.  
  22.  
  23. template <typename T>
  24. class CallUp : public CallUp<GetBaseType<T>>
  25. {
  26. public:
  27. template <typename Op>
  28. CallUp(Op&& op, T& obj) : CallUp<GetBaseType<T>>(op, obj), op(std::forward<Op>(op)), obj(obj)
  29. {}
  30. ~CallUp()
  31. {
  32. op(obj);
  33. }
  34. private:
  35. std::function<void(T&)> op;
  36. T& obj;
  37. };
  38.  
  39.  
  40. template <typename T>
  41. class ConstCallUp;
  42.  
  43. template <>
  44. class ConstCallUp<NoBase>
  45. {
  46. public:
  47. template <typename Op, typename T>
  48. ConstCallUp(Op&& ignoreOperation, T&& ignoreObject) {}
  49. };
  50.  
  51. template <typename T>
  52. class ConstCallUp : public ConstCallUp<GetBaseType<T>>
  53. {
  54. public:
  55. template <typename Op>
  56. ConstCallUp(Op&& op, const T& obj) : ConstCallUp<GetBaseType<T>>(op, obj), op(std::forward<Op>(op)), obj(obj)
  57. {}
  58. ~ConstCallUp()
  59. {
  60. op(obj);
  61. }
  62. private:
  63. std::function<void(T&)> op;
  64. const T& obj;
  65. };
  66.  
  67. template <typename ...T>
  68. struct MultiBases {};
  69.  
  70. template <typename ...T>
  71. class CallUp<MultiBases<T...>> : public CallUp<T>...
  72. {
  73. public:
  74. template <typename Derived, typename Op>
  75. CallUp(Op&& op, Derived& obj) : CallUp<T>(op, obj)...
  76. {}
  77. };
  78. template <typename ...T>
  79. class ConstCallUp<MultiBases<T...>> : public ConstCallUp<T>...
  80. {
  81. public:
  82. template <typename Derived, typename Op>
  83. ConstCallUp(Op&& op, Derived& obj) : ConstCallUp<T>(op, obj)...
  84. {}
  85. };
  86.  
  87. template <typename Op, typename T>
  88. auto callUp(Op&& op, T& obj)
  89. {
  90. return CallUp<T>(std::forward<Op>(op), obj);
  91. }
  92. template <typename Op, typename T>
  93. auto callUp(Op&& op, const T& obj)
  94. {
  95. return ConstCallUp<T>(std::forward<Op>(op), obj);
  96. }
  97.  
  98. class Foo01
  99. {
  100. public:
  101. using Base = NoBase;
  102. virtual void reset()
  103. {
  104. std::cout << "reset Foo01\n";
  105. }
  106. void print() const
  107. {
  108. std::cout << "Foo01\n";
  109. }
  110. };
  111.  
  112. class Foo02
  113. {
  114. public:
  115. using Base = NoBase;
  116. void reset()
  117. {
  118. std::cout << "reset Foo02\n";
  119. }
  120. void print() const
  121. {
  122. std::cout << "Foo02\n";
  123. }
  124. };
  125.  
  126.  
  127. class Foo1 : public Foo01, public Foo02
  128. {
  129. public:
  130. using Base = MultiBases<Foo01, Foo02>;
  131. void reset()
  132. {
  133. std::cout << "reset Foo1\n";
  134. }
  135. void print() const
  136. {
  137. std::cout << "Foo1\n";
  138. }
  139. };
  140.  
  141. class Foo2 : public Foo1
  142. {
  143. public:
  144. using Base = Foo1;
  145. void reset()
  146. {
  147. std::cout << "reset Foo2\n";
  148. }
  149. void print() const
  150. {
  151. std::cout << "Foo2\n";
  152. }
  153. };
  154.  
  155. template <typename T>
  156. using object_class_t = std::remove_cv_t<std::remove_reference_t<T>>;
  157.  
  158. int main() {
  159. Foo2 foo2;
  160. callUp([](auto&& obj){ using ObjClass = object_class_t<decltype(obj)>; obj.ObjClass::reset();}, foo2);
  161. callUp([](auto&& obj){obj.print();}, foo2);
  162. }
Success #stdin #stdout 0s 3416KB
stdin
Standard input is empty
stdout
reset Foo2
reset Foo1
reset Foo02
reset Foo01
Foo2
Foo1
Foo02
Foo01