#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
//folgendes wäre Teil der Standardlibrary
//nur minimale features implementiert (zeitgründe)
class Integer {
public:
typedef int BaseType;
int value;
Integer(int value=0) : value(value) {}
Integer(Integer const& other) : value(other.value) {}
Integer& operator=(Integer const& other) {
value=other.value;
return *this;
}
};
Integer operator+(Integer const& lhs, Integer const& rhs) {
return Integer(lhs.value+rhs.value);
}
class PositiveInteger : protected Integer {
public:
typedef int BaseType;
PositiveInteger(int value=0) : Integer(value) { if(value<0) throw "Negative Value"; }
PositiveInteger(Integer const& other) : Integer(other) { if(value<0) throw "Negative Value"; }
PositiveInteger& operator=(Integer const& other) {
if(other.value < 0) throw "Negative Value";
value=other.value;
return *this;
}
operator Integer() { return *this; }
};
template<typename T>
class Vector {
private:
vector<T> impl;
public:
void add(T const& val) {
impl.push_back(val);
}
template<typename F>
void for_each(F f) {
for(auto& obj : impl) {
f(obj);
}
}
};
template<typename T>
class ChangeObserver : public Vector<function<void(T const&, T const&)> > {
public:
void change(T const& oldVal, T const& newVal) {
this->for_each([&](function<void(T const&, T const&)> f) { f(oldVal, newVal); });
}
};
template<typename ValueType>
class ChangeObservableArithmeticType : private ValueType, public ChangeObserver<ValueType> {
public:
typedef typename ValueType::BaseType BaseType;
ChangeObservableArithmeticType(typename ValueType::BaseType value=0) : ValueType(value) {}
ChangeObservableArithmeticType(ChangeObservableArithmeticType const& other) : ValueType(other) {}
ChangeObservableArithmeticType(ValueType const& other) : ValueType(other) {}
ChangeObservableArithmeticType& operator=(ChangeObservableArithmeticType const& other) {
this->change(*this, other);
this->value=other.value;
return *this;
}
operator ValueType() {
return *this;
}
};
class Radius : public ChangeObservableArithmeticType<PositiveInteger> {
};
class Kreis : public Radius {
public:
Kreis() {
add([&](::PositiveInteger const&, ::PositiveInteger const&) {
redraw();
});
redraw();
}
void redraw() {
cout<<"Radius changed, Kreis redrawn\n";
}
};
int main() {
//2x redraw ausführen:
Kreis k;
k.ChangeObservableArithmeticType::operator=(7);
try {
k.ChangeObservableArithmeticType::operator=(-7);
} catch(...) {
cout<<"Error\n";
}
return 0;
}