#pragma once namespace types { template struct Boolean { operator bool() const { return static_cast(*this).get(); } }; template struct Incrementable { friend Self operator++(Self & self, int) { Self copy = self; self = Self(self.get() + 1); return copy; } friend Self & operator++(Self & self) { return self = Self(self.get() + 1); } }; template struct Decrementable { friend Self operator--(Self & self, int) { Self copy = self; self = Self(self.get() - 1); return copy; } friend Self & operator--(Self & self) { return self = Self(self.get() - 1); } }; template struct Addable { friend Self operator+(Self const & lhs, Self const & rhs) { return Self(lhs.get() + rhs.get()); } }; template struct Arithmetic : Addable { friend Self operator-(Self const & self) { return Self(-self.get()); } friend Self operator-(Self const & lhs, Self const & rhs) { return Self(lhs.get() - rhs.get()); } }; template struct Numeric : Arithmetic { friend Self operator*(Self const & lhs, Self const & rhs) { return Self(lhs.get() * rhs.get()); } friend Self operator/(Self const & lhs, Self const & rhs) { return Self(lhs.get() / rhs.get()); } }; }