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.   from& operator+=(from const& other) { \
  14.   to::operator+=(other); return *this; \
  15.   } \
  16.   from& operator-=(from const& other) { \
  17.   to::operator-=(other); return *this; \
  18.   } \
  19.   from& operator*=(from const& other) { \
  20.   to::operator*=(other); return *this; \
  21.   } \
  22.   from& operator/=(from const& other) { \
  23.   to::operator/=(other); return *this; \
  24.   } \
  25.   friend from operator+(from const& lhs, from const& rhs) { \
  26.   return operator+(lhs.operator to(), rhs.operator to()); \
  27.   } \
  28.   friend from operator-(from const& lhs, from const& rhs) { \
  29.   return operator-(lhs.operator to(), rhs.operator to()); \
  30.   } \
  31.   friend from operator*(from const& lhs, from const& rhs) { \
  32.   return operator*(lhs.operator to(), rhs.operator to()); \
  33.   } \
  34.   friend from operator/(from const& lhs, from const& rhs) { \
  35.   return operator/(lhs.operator to(), rhs.operator to()); \
  36.   }
  37.  
  38. //folgendes wäre Teil der Standardlibrary
  39. //nur minimale features implementiert (zeitgründe)
  40. class Integer {
  41. public:
  42. typedef int BaseType;
  43. int value;
  44.  
  45. Integer(int value=0) : value(value) {}
  46. Integer(Integer const& other) : value(other.value) {}
  47.  
  48. Integer& operator=(Integer const& other) {
  49. value=other.value;
  50. return *this;
  51. }
  52.  
  53. Integer& operator+=(Integer const& other) {
  54. value+=other.value;
  55. return *this;
  56. }
  57. Integer& operator-=(Integer const& other) {
  58. value-=other.value;
  59. return *this;
  60. }
  61. Integer& operator*=(Integer const& other) {
  62. value*=other.value;
  63. return *this;
  64. }
  65. Integer& operator/=(Integer const& other) {
  66. value/=other.value;
  67. return *this;
  68. }
  69.  
  70. };
  71.  
  72. Integer operator+(Integer const& lhs, Integer const& rhs) {
  73. return Integer(lhs.value+rhs.value);
  74. }
  75. Integer operator-(Integer const& lhs, Integer const& rhs) {
  76. return Integer(lhs.value-rhs.value);
  77. }
  78. Integer operator*(Integer const& lhs, Integer const& rhs) {
  79. return Integer(lhs.value*rhs.value);
  80. }
  81. Integer operator/(Integer const& lhs, Integer const& rhs) {
  82. return Integer(lhs.value/rhs.value);
  83. }
  84.  
  85.  
  86. class PositiveInteger : protected Integer {
  87. public:
  88. typedef int BaseType;
  89.  
  90. PositiveInteger(int value=0) : Integer(value) { if(value<0) throw "Negative Value"; }
  91. PositiveInteger(Integer const& other) : Integer(other) { if(value<0) throw "Negative Value"; }
  92.  
  93. PositiveInteger& operator=(Integer const& other) {
  94. if(other.value < 0) throw "Negative Value";
  95. value=other.value;
  96. return *this;
  97. }
  98.  
  99. operator Integer() const { return *this; }
  100. FORWARD_ARITHMETIC_OPS(PositiveInteger, Integer)
  101. };
  102.  
  103.  
  104.  
  105.  
  106. template<typename T>
  107. class Vector {
  108. private:
  109. vector<T> impl;
  110.  
  111. public:
  112. void add(T const& val) {
  113. impl.push_back(val);
  114. }
  115.  
  116. template<typename F>
  117. void for_each(F f) {
  118. for(auto& obj : impl) {
  119. f(obj);
  120. }
  121. }
  122. };
  123.  
  124. template<typename T>
  125. class ChangeObserver : public Vector<function<void(T const&, T const&)> > {
  126. public:
  127. void change(T const& oldVal, T const& newVal) {
  128. this->for_each([&](function<void(T const&, T const&)> f) { f(oldVal, newVal); });
  129. }
  130. };
  131.  
  132. template<typename ValueType>
  133. class ChangeObservableArithmeticType : protected ValueType, public ChangeObserver<ValueType> {
  134. public:
  135. typedef typename ValueType::BaseType BaseType;
  136. ChangeObservableArithmeticType(typename ValueType::BaseType value=0) : ValueType(value) {}
  137. ChangeObservableArithmeticType(ChangeObservableArithmeticType const& other) : ValueType(other) {}
  138. ChangeObservableArithmeticType(ValueType const& other) : ValueType(other) {}
  139.  
  140. ChangeObservableArithmeticType& operator=(ChangeObservableArithmeticType const& other) {
  141. this->change(*this, other);
  142. this->value=other.value;
  143. return *this;
  144. }
  145.  
  146. operator ValueType() const {
  147. return *this;
  148. }
  149.  
  150. FORWARD_ARITHMETIC_OPS(ChangeObservableArithmeticType, ValueType)
  151. };
  152.  
  153.  
  154.  
  155. class Radius : public ChangeObservableArithmeticType<PositiveInteger> {
  156. public:
  157. Radius() {}
  158. Radius(ChangeObservableArithmeticType::BaseType value) : ChangeObservableArithmeticType(value) {}
  159. PositiveInteger const& asPositiveInteger() const {
  160. return *this;
  161. }
  162.  
  163. FORWARD_ASSIGN(Radius, ChangeObservableArithmeticType)
  164. };
  165.  
  166. class Punkt : public Integer {
  167. public:
  168. FORWARD_ASSIGN(Punkt, Integer)
  169. Punkt(int val) : Integer(val) {}
  170. };
  171.  
  172. class PunktX : public Punkt { public: FORWARD_ASSIGN(PunktX, Punkt) PunktX(int val):Punkt(val){} };
  173. class PunktY : public Punkt { public: FORWARD_ASSIGN(PunktY, Punkt) PunktY(int val):Punkt(val){} };
  174.  
  175. class PunktXY : public PunktX, public PunktY {
  176. public:
  177. PunktXY(int x=0, int y=0) : PunktX(x), PunktY(y) {}
  178. };
  179.  
  180. class Startpunkt : public PunktXY { public: FORWARD_ASSIGN(Startpunkt, PunktXY) };
  181. class Endpunkt : public PunktXY { public: FORWARD_ASSIGN(Endpunkt, PunktXY) };
  182.  
  183. class Kreis : public Radius, public PunktXY {
  184. public:
  185. Kreis(int r) : Radius(r) {
  186. Radius::add([&](::PositiveInteger const&, ::PositiveInteger const&) {
  187. redraw();
  188. });
  189.  
  190. redraw();
  191. }
  192.  
  193. void redraw() {
  194. cout<<"Radius changed, Kreis redrawn\n";
  195. }
  196. };
  197.  
  198. class Laenge : public Integer { public: FORWARD_ASSIGN(Laenge, Integer) };
  199.  
  200. class Strecke : public Startpunkt, public Endpunkt {
  201. public:
  202. Strecke() : Startpunkt(PunktXY(0,0)), Endpunkt(PunktXY(0,0)) {}
  203. };
  204.  
  205. class Rechteck : public PunktXY, public Laenge {
  206. public:
  207. Rechteck(int laenge) : Laenge(laenge) {}
  208. };
  209.  
  210. void verdoppleRadius(Radius& r) {
  211. r=r*2;
  212. }
  213.  
  214. void printKoordinaten(PunktXY const& p) {
  215. cout<<"("<<p.PunktX::value<<"/"<<p.PunktY::value<<")\n";
  216. }
  217.  
  218. void wierdShit(Kreis& k, Laenge& l) {
  219. l=l*static_cast<PunktX&>(k)+static_cast<PunktY&>(k);
  220. }
  221.  
  222. int main() {
  223.  
  224. Kreis k(3);
  225. Rechteck r(12);
  226. Strecke s;
  227.  
  228. k.PunktXY::operator=(PunktXY(10,20));
  229. r.PunktXY::operator=(PunktXY(1,2));
  230. s.Startpunkt::operator=(PunktXY(5,7));
  231. s.Endpunkt::operator=(PunktXY(15,17));
  232.  
  233. //2x redraw ausführen:
  234. k.Radius::operator=(7);
  235.  
  236. try {
  237. //force error
  238. k.Radius::operator=(-7);
  239. } catch(...) {
  240. cout<<"Error\n";
  241. }
  242.  
  243. verdoppleRadius(k);
  244.  
  245. printKoordinaten(k);
  246. printKoordinaten(r);
  247. printKoordinaten(static_cast<Startpunkt&>(s));
  248.  
  249.  
  250.  
  251. return 0;
  252. }
  253.  
  254.  
Success #stdin #stdout 0s 2988KB
stdin
Standard input is empty
stdout
Radius changed, Kreis redrawn
Radius changed, Kreis redrawn
Error
Radius changed, Kreis redrawn
(10/20)
(1/2)
(5/7)