fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <functional>
  4. #include <algorithm>
  5. #include <string>
  6.  
  7. using namespace std;
  8.  
  9. #define FORWARD_ASSIGN(from, to) \
  10.   from(to const& other) : to(other) {} \
  11.   from const& operator=(from const& other) { to::operator=(other); return *this; }
  12.  
  13. #define FORWARD_ARITHMETIC_OPS(from, to) \
  14.   from& operator+=(from const& other) { \
  15.   to::operator+=(other); return *this; \
  16.   } \
  17.   from& operator-=(from const& other) { \
  18.   to::operator-=(other); return *this; \
  19.   } \
  20.   from& operator*=(from const& other) { \
  21.   to::operator*=(other); return *this; \
  22.   } \
  23.   from& operator/=(from const& other) { \
  24.   to::operator/=(other); return *this; \
  25.   } \
  26.   friend from operator+(from const& lhs, from const& rhs) { \
  27.   return operator+(lhs.operator to(), rhs.operator to()); \
  28.   } \
  29.   friend from operator-(from const& lhs, from const& rhs) { \
  30.   return operator-(lhs.operator to(), rhs.operator to()); \
  31.   } \
  32.   friend from operator*(from const& lhs, from const& rhs) { \
  33.   return operator*(lhs.operator to(), rhs.operator to()); \
  34.   } \
  35.   friend from operator/(from const& lhs, from const& rhs) { \
  36.   return operator/(lhs.operator to(), rhs.operator to()); \
  37.   }
  38.  
  39. //folgendes wäre Teil der Standardlibrary
  40. //nur minimale features implementiert (zeitgründe)
  41. class Integer {
  42. public:
  43. typedef int BaseType;
  44. int value;
  45.  
  46. Integer(int value=0) : value(value) {}
  47. Integer(Integer const& other) : value(other.value) {}
  48.  
  49. Integer& operator=(Integer const& other) {
  50. value=other.value;
  51. return *this;
  52. }
  53.  
  54. Integer& operator+=(Integer const& other) {
  55. value+=other.value;
  56. return *this;
  57. }
  58. Integer& operator-=(Integer const& other) {
  59. value-=other.value;
  60. return *this;
  61. }
  62. Integer& operator*=(Integer const& other) {
  63. value*=other.value;
  64. return *this;
  65. }
  66. Integer& operator/=(Integer const& other) {
  67. value/=other.value;
  68. return *this;
  69. }
  70.  
  71. };
  72.  
  73. Integer operator+(Integer const& lhs, Integer const& rhs) {
  74. return Integer(lhs.value+rhs.value);
  75. }
  76. Integer operator-(Integer const& lhs, Integer const& rhs) {
  77. return Integer(lhs.value-rhs.value);
  78. }
  79. Integer operator*(Integer const& lhs, Integer const& rhs) {
  80. return Integer(lhs.value*rhs.value);
  81. }
  82. Integer operator/(Integer const& lhs, Integer const& rhs) {
  83. return Integer(lhs.value/rhs.value);
  84. }
  85.  
  86.  
  87. class PositiveInteger : protected Integer {
  88. public:
  89. typedef int BaseType;
  90.  
  91. PositiveInteger(int value=0) : Integer(value) { if(value<0) throw "Negative Value"; }
  92. PositiveInteger(Integer const& other) : Integer(other) { if(value<0) throw "Negative Value"; }
  93.  
  94. PositiveInteger& operator=(Integer const& other) {
  95. if(other.value < 0) throw "Negative Value";
  96. value=other.value;
  97. return *this;
  98. }
  99.  
  100. operator Integer() const { return *this; }
  101. FORWARD_ARITHMETIC_OPS(PositiveInteger, Integer)
  102. };
  103.  
  104.  
  105.  
  106.  
  107. template<typename T>
  108. class Vector : public vector<T> {
  109. public:
  110. void add(T const& val) {
  111. this->push_back(val);
  112. }
  113.  
  114. template<typename F>
  115. void for_each(F f) {
  116. for(auto& obj : *this) {
  117. f(obj);
  118. }
  119. }
  120. };
  121.  
  122. template<typename T>
  123. class ChangeObserver : public Vector<function<void(T const&, T const&)> > {
  124. public:
  125. void change(T const& oldVal, T const& newVal) {
  126. this->for_each([&](function<void(T const&, T const&)> f) { f(oldVal, newVal); });
  127. }
  128. };
  129.  
  130. template<typename ValueType>
  131. class ChangeObservableArithmeticType : protected ValueType, public ChangeObserver<ValueType> {
  132. public:
  133. typedef typename ValueType::BaseType BaseType;
  134. ChangeObservableArithmeticType(typename ValueType::BaseType value=0) : ValueType(value) {}
  135. ChangeObservableArithmeticType(ChangeObservableArithmeticType const& other) : ValueType(other) {}
  136. ChangeObservableArithmeticType(ValueType const& other) : ValueType(other) {}
  137.  
  138. ChangeObservableArithmeticType& operator=(ChangeObservableArithmeticType const& other) {
  139. this->change(*this, other);
  140. this->value=other.value;
  141. return *this;
  142. }
  143.  
  144. operator ValueType() const {
  145. return *this;
  146. }
  147.  
  148. FORWARD_ARITHMETIC_OPS(ChangeObservableArithmeticType, ValueType)
  149. };
  150.  
  151.  
  152.  
  153. class Radius : public ChangeObservableArithmeticType<PositiveInteger> {
  154. public:
  155. Radius() {}
  156. Radius(ChangeObservableArithmeticType::BaseType value) : ChangeObservableArithmeticType(value) {}
  157. PositiveInteger const& asPositiveInteger() const {
  158. return *this;
  159. }
  160.  
  161. FORWARD_ASSIGN(Radius, ChangeObservableArithmeticType)
  162. };
  163.  
  164. class Punkt : public Integer {
  165. public:
  166. FORWARD_ASSIGN(Punkt, Integer)
  167. Punkt(int val) : Integer(val) {}
  168. };
  169.  
  170. class PunktX : public Punkt { public: FORWARD_ASSIGN(PunktX, Punkt) PunktX(int val):Punkt(val){} };
  171. class PunktY : public Punkt { public: FORWARD_ASSIGN(PunktY, Punkt) PunktY(int val):Punkt(val){} };
  172.  
  173. class PunktXY : public PunktX, public PunktY {
  174. public:
  175. PunktXY(int x=0, int y=0) : PunktX(x), PunktY(y) {}
  176. };
  177.  
  178. class Startpunkt : public PunktXY { public: FORWARD_ASSIGN(Startpunkt, PunktXY) };
  179. class Endpunkt : public PunktXY { public: FORWARD_ASSIGN(Endpunkt, PunktXY) };
  180.  
  181. class Kreis : public Radius, public PunktXY {
  182. public:
  183. Kreis(int r) : Radius(r) {
  184. Radius::add([&](::PositiveInteger const&, ::PositiveInteger const&) {
  185. redraw();
  186. });
  187.  
  188. redraw();
  189. }
  190.  
  191. void redraw() {
  192. cout<<"Radius changed, Kreis redrawn\n";
  193. }
  194. };
  195.  
  196. class Laenge : public Integer { public: FORWARD_ASSIGN(Laenge, Integer) };
  197.  
  198. class Strecke : public Startpunkt, public Endpunkt {
  199. public:
  200. Strecke() : Startpunkt(PunktXY(0,0)), Endpunkt(PunktXY(0,0)) {}
  201. };
  202.  
  203. class Rechteck : public PunktXY, public Laenge {
  204. public:
  205. Rechteck(int laenge) : Laenge(laenge) {}
  206. };
  207.  
  208. void verdoppleRadius(Radius& r) {
  209. r=r*2;
  210. }
  211.  
  212. void printKoordinaten(PunktXY const& p) {
  213. cout<<"("<<p.PunktX::value<<"/"<<p.PunktY::value<<")\n";
  214. }
  215.  
  216. void wierdShit(Kreis& k, Laenge& l) {
  217. l=l*static_cast<PunktX&>(k)+static_cast<PunktY&>(k);
  218. }
  219.  
  220.  
  221. class Motor : public Integer {
  222. public:
  223. Motor(int ps) : Integer(ps) {}
  224. FORWARD_ASSIGN(Motor, Integer)
  225. };
  226.  
  227. //eigentlich : public Boolean, aber ich bin zu faul einen bool zu implementeiren
  228. template<typename Position>
  229. class Tuere : public Integer, public Position {
  230. public:
  231. Tuere(int isOpen=0) : Integer(isOpen) {}
  232.  
  233. FORWARD_ASSIGN(Tuere, Integer)
  234. };
  235.  
  236.  
  237. class Position : public string {
  238. public:
  239. FORWARD_ASSIGN(Position, string)
  240. };
  241.  
  242. class LinksHinten : public Position {
  243. public:
  244. LinksHinten() : Position("LinksHinten") {}
  245. FORWARD_ASSIGN(LinksHinten, Position)
  246. };
  247.  
  248. class LinksVorne : public Position {
  249. public:
  250. LinksVorne() : Position("LinksVorne") {}
  251. FORWARD_ASSIGN(LinksVorne, Position)
  252. };
  253.  
  254. class RechtsHinten : public Position {
  255. public:
  256. RechtsHinten() : Position("RechtsHinten") {}
  257. FORWARD_ASSIGN(RechtsHinten, Position)
  258. };
  259.  
  260. class RechtsVorne : public Position {
  261. public:
  262. RechtsVorne() : Position("RechtsVorne") {}
  263. FORWARD_ASSIGN(RechtsVorne, Position)
  264. };
  265.  
  266. class Fuellstand : public ChangeObservableArithmeticType<PositiveInteger> {
  267. public:
  268. FORWARD_ASSIGN(Fuellstand, ChangeObservableArithmeticType)
  269.  
  270. operator ChangeObservableArithmeticType() const {
  271. return *this;
  272. }
  273. FORWARD_ARITHMETIC_OPS(Fuellstand, ChangeObservableArithmeticType)
  274. };
  275.  
  276. class Maximalstand : public PositiveInteger {
  277. public:
  278. FORWARD_ASSIGN(Maximalstand, PositiveInteger)
  279. };
  280.  
  281. class Tank : private Maximalstand, private Fuellstand {
  282. public:
  283. Tank(int liter) : Maximalstand(liter), Fuellstand(liter) {
  284. Fuellstand::add([&](::PositiveInteger const&, ::PositiveInteger const& newVal) {
  285. if(newVal.operator ::Integer().value > Maximalstand::operator ::Integer().value)
  286. throw "zu hoher Fuellstand";
  287. });
  288. }
  289.  
  290. bool isVoll() const { return Maximalstand::operator ::Integer().value == Fuellstand::value; }
  291.  
  292. operator Fuellstand() const {
  293. return *this;
  294. }
  295. FORWARD_ARITHMETIC_OPS(Tank, Fuellstand)
  296.  
  297. };
  298.  
  299. class Geschwindigkeit : public Integer {
  300. public:
  301. Geschwindigkeit(int kmh) : Integer(kmh) {}
  302. FORWARD_ASSIGN(Geschwindigkeit, Integer)
  303. };
  304.  
  305. class Name : public string {
  306. public:
  307. FORWARD_ASSIGN(Name, string)
  308. };
  309.  
  310. class Auto
  311. : public Motor
  312. , public Tuere<LinksHinten>, public Tuere<LinksVorne>, public Tuere<RechtsHinten>, public Tuere<RechtsVorne>
  313. , protected Geschwindigkeit, protected Tank, public Name {
  314. public:
  315. Auto(Name const& name, Tank const& tank) : Tank(tank), Name(name), Geschwindigkeit(0) {}
  316.  
  317. void gasgeben() {
  318. Geschwindigkeit::operator+=(10);
  319. }
  320.  
  321. void bremsen() {
  322. Geschwindigkeit::operator -=(10);
  323. }
  324.  
  325. void tick() {
  326. //10kmh kosten 1 liter pro tick
  327. PositiveInteger kosten = Geschwindigkeit::value/10;
  328. Tank::operator-=(kosten);
  329. }
  330.  
  331. operator Geschwindigkeit() {
  332. return *this;
  333. }
  334. };
  335.  
  336. int main() {
  337. Auto merzedes;
  338. merzedes.Motor::operator=(100); //set PS
  339. merzedes.gasgeben();
  340. merzedes.gasgeben();
  341.  
  342. merzedes.tick();
  343. return 0;
  344. }
  345.  
  346. void rumspielen() {
  347.  
  348. Kreis k(3);
  349. Rechteck r(12);
  350. Strecke s;
  351.  
  352. k.PunktXY::operator=(PunktXY(10,20));
  353. r.PunktXY::operator=(PunktXY(1,2));
  354. s.Startpunkt::operator=(PunktXY(5,7));
  355. s.Endpunkt::operator=(PunktXY(15,17));
  356.  
  357. //2x redraw ausführen:
  358. k.Radius::operator=(7);
  359.  
  360. try {
  361. //force error
  362. k.Radius::operator=(-7);
  363. } catch(...) {
  364. cout<<"Error\n";
  365. }
  366.  
  367. verdoppleRadius(k);
  368.  
  369. printKoordinaten(k);
  370. printKoordinaten(r);
  371. printKoordinaten(static_cast<Startpunkt&>(s));
  372. }
  373.  
  374.  
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp: In function ‘Tank operator+(const Tank&, const Tank&)’:
prog.cpp:295:5: error: could not convert ‘operator+(const Fuellstand&, const Fuellstand&)((*(const Fuellstand*)(& Tank::operator Fuellstand() const())))’ from ‘Fuellstand’ to ‘Tank’
prog.cpp: In function ‘Tank operator-(const Tank&, const Tank&)’:
prog.cpp:295:5: error: could not convert ‘operator-(const Fuellstand&, const Fuellstand&)((*(const Fuellstand*)(& Tank::operator Fuellstand() const())))’ from ‘Fuellstand’ to ‘Tank’
prog.cpp: In function ‘Tank operator*(const Tank&, const Tank&)’:
prog.cpp:295:5: error: could not convert ‘operator*(const Fuellstand&, const Fuellstand&)((*(const Fuellstand*)(& Tank::operator Fuellstand() const())))’ from ‘Fuellstand’ to ‘Tank’
prog.cpp: In function ‘Tank operator/(const Tank&, const Tank&)’:
prog.cpp:295:5: error: could not convert ‘operator/(const Fuellstand&, const Fuellstand&)((*(const Fuellstand*)(& Tank::operator Fuellstand() const())))’ from ‘Fuellstand’ to ‘Tank’
prog.cpp: In constructor ‘Auto::Auto(const Name&, const Tank&)’:
prog.cpp:315:89: warning: base ‘Name’ will be initialized after [-Wreorder]
prog.cpp:315:89: warning:   base ‘Geschwindigkeit’ [-Wreorder]
prog.cpp:315:5: warning:   when initialized here [-Wreorder]
prog.cpp:315:89: error: no matching function for call to ‘Motor::Motor()’
prog.cpp:315:89: note: candidates are:
prog.cpp:224:5: note: Motor::Motor(const Integer&)
prog.cpp:224:5: note:   candidate expects 1 argument, 0 provided
prog.cpp:223:5: note: Motor::Motor(int)
prog.cpp:223:5: note:   candidate expects 1 argument, 0 provided
prog.cpp:221:7: note: Motor::Motor(const Motor&)
prog.cpp:221:7: note:   candidate expects 1 argument, 0 provided
prog.cpp: In member function ‘void Auto::tick()’:
prog.cpp:87:43: error: ‘class PositiveInteger PositiveInteger::PositiveInteger’ is inaccessible
prog.cpp:327:25: error: within this context
prog.cpp:328:32: error: no matching function for call to ‘Auto::operator-=(PositiveInteger&)’
prog.cpp:328:32: note: candidate is:
prog.cpp:295:5: note: Tank& Tank::operator-=(const Tank&)
prog.cpp:295:5: note:   no known conversion for argument 1 from ‘PositiveInteger’ to ‘const Tank&’
prog.cpp: In function ‘int main()’:
prog.cpp:337:10: error: no matching function for call to ‘Auto::Auto()’
prog.cpp:337:10: note: candidates are:
prog.cpp:315:5: note: Auto::Auto(const Name&, const Tank&)
prog.cpp:315:5: note:   candidate expects 2 arguments, 0 provided
prog.cpp:310:7: note: Auto::Auto(const Auto&)
prog.cpp:310:7: note:   candidate expects 1 argument, 0 provided
stdout
Standard output is empty