fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <functional>
  4. #include <algorithm>
  5.  
  6. using namespace std;
  7.  
  8. #define FORWARD_ASSIGN(from, to) \
  9.   from(to const& other) : to(other) {} \
  10.   from const& operator=(from const& other) { to::operator=(other); return *this; }
  11.  
  12. #define FORWARD_ARITHMETIC_OPS(from, to) \
  13.   friend from operator+(from const& lhs, from const& rhs) { \
  14.   return operator+(lhs.operator to(), rhs.operator to()); \
  15.   }
  16.  
  17. //folgendes wäre Teil der Standardlibrary
  18. //nur minimale features implementiert (zeitgründe)
  19. class Integer {
  20. public:
  21. typedef int BaseType;
  22. int value;
  23.  
  24. Integer(int value=0) : value(value) {}
  25. Integer(Integer const& other) : value(other.value) {}
  26.  
  27. Integer& operator=(Integer const& other) {
  28. value=other.value;
  29. return *this;
  30. }
  31. };
  32.  
  33. Integer operator+(Integer const& lhs, Integer const& rhs) {
  34. return Integer(lhs.value+rhs.value);
  35. }
  36.  
  37. class PositiveInteger : protected Integer {
  38. public:
  39. typedef int BaseType;
  40.  
  41. PositiveInteger(int value=0) : Integer(value) { if(value<0) throw "Negative Value"; }
  42. PositiveInteger(Integer const& other) : Integer(other) { if(value<0) throw "Negative Value"; }
  43.  
  44. PositiveInteger& operator=(Integer const& other) {
  45. if(other.value < 0) throw "Negative Value";
  46. value=other.value;
  47. return *this;
  48. }
  49.  
  50. operator Integer() const { return *this; }
  51. FORWARD_ARITHMETIC_OPS(PositiveInteger, Integer)
  52. };
  53.  
  54.  
  55.  
  56.  
  57. template<typename T>
  58. class Vector {
  59. private:
  60. vector<T> impl;
  61.  
  62. public:
  63. void add(T const& val) {
  64. impl.push_back(val);
  65. }
  66.  
  67. template<typename F>
  68. void for_each(F f) {
  69. for(auto& obj : impl) {
  70. f(obj);
  71. }
  72. }
  73. };
  74.  
  75. template<typename T>
  76. class ChangeObserver : public Vector<function<void(T const&, T const&)> > {
  77. public:
  78. void change(T const& oldVal, T const& newVal) {
  79. this->for_each([&](function<void(T const&, T const&)> f) { f(oldVal, newVal); });
  80. }
  81. };
  82.  
  83. template<typename ValueType>
  84. class ChangeObservableArithmeticType : protected ValueType, public ChangeObserver<ValueType> {
  85. public:
  86. typedef typename ValueType::BaseType BaseType;
  87. ChangeObservableArithmeticType(typename ValueType::BaseType value=0) : ValueType(value) {}
  88. ChangeObservableArithmeticType(ChangeObservableArithmeticType const& other) : ValueType(other) {}
  89. ChangeObservableArithmeticType(ValueType const& other) : ValueType(other) {}
  90.  
  91. ChangeObservableArithmeticType& operator=(ChangeObservableArithmeticType const& other) {
  92. this->change(*this, other);
  93. this->value=other.value;
  94. return *this;
  95. }
  96.  
  97. operator ValueType() const {
  98. return *this;
  99. }
  100.  
  101. FORWARD_ARITHMETIC_OPS(ChangeObservableArithmeticType, ValueType)
  102. };
  103.  
  104.  
  105.  
  106. class Radius : public ChangeObservableArithmeticType<PositiveInteger> {
  107. public:
  108. Radius() {}
  109. Radius(ChangeObservableArithmeticType::BaseType value) : ChangeObservableArithmeticType(value) {}
  110. PositiveInteger const& asPositiveInteger() const {
  111. return *this;
  112. }
  113.  
  114. FORWARD_ASSIGN(Radius, ChangeObservableArithmeticType)
  115. };
  116.  
  117. class Kreis : public Radius {
  118. public:
  119. Kreis() {
  120. add([&](::PositiveInteger const&, ::PositiveInteger const&) {
  121. redraw();
  122. });
  123.  
  124. redraw();
  125. }
  126.  
  127. void redraw() {
  128. cout<<"Radius changed, Kreis redrawn\n";
  129. }
  130. };
  131.  
  132. void verdoppleRadius(Radius& r) {
  133. r=r+r;
  134. }
  135.  
  136. int main() {
  137. //2x redraw ausführen:
  138. Kreis k;
  139. k.Radius::operator=(7);
  140.  
  141. try {
  142. k.Radius::operator=(-7);
  143. } catch(...) {
  144. cout<<"Error\n";
  145. }
  146.  
  147. verdoppleRadius(k);
  148.  
  149. return 0;
  150. }
  151.  
  152.  
Success #stdin #stdout 0s 2988KB
stdin
Standard input is empty
stdout
Radius changed, Kreis redrawn
Radius changed, Kreis redrawn
Error
Radius changed, Kreis redrawn