#ifndef OB_NUM_HH #define OB_NUM_HH #include #include #include #include #include #include namespace OB { template class basic_num { public: basic_num(T val) noexcept : _val {val} { } basic_num(T val, T min, T max) noexcept : _val {val}, _min {min}, _max {max} { } basic_num() = default; basic_num(basic_num const&) = default; basic_num(basic_num&&) = default; basic_num& operator=(basic_num const&) = default; basic_num& operator=(basic_num&&) = default; basic_num& operator=(T const val) { validate(val); return *this; } ~basic_num() = default; template friend std::ostream& operator<<(std::ostream& os, basic_num const& obj); template friend std::istream& operator>>(std::istream& is, basic_num& obj); T get() const { return _val; } template, int> = 0> V get() const { return static_cast(_val); } operator bool() const { return static_cast(_val); } operator std::string() const { return str(); } bool operator!() const { return ! static_cast(*this); } basic_num& operator++() { *this += 1; return *this; } basic_num& operator--() { *this -= 1; return *this; } basic_num operator++(int) { basic_num tmp {*this}; operator++(); return tmp; } basic_num operator--(int) { basic_num tmp {*this}; operator--(); return tmp; } template inline basic_num operator+(basic_num const& obj) { *this += obj; return *this; } template inline basic_num operator-(basic_num const& obj) { *this -= obj; return *this; } template inline basic_num operator*(V const& obj) { *this *= obj; return *this; } template inline basic_num operator/(V const& obj) { *this /= obj; return *this; } template inline basic_num operator%(V const& obj) { *this %= obj; return *this; } template inline bool operator<(V const& obj) const { return _val < obj; } template inline bool operator>(V const& obj) const { return obj < *this; } template inline bool operator<=(V const& obj) const { return !(*this > obj); } template inline bool operator>=(V const& obj) const { return !(*this < obj); } template inline bool operator==(V const& obj) const { return _val == obj; } template inline bool operator!=(V const& obj) const { return !(*this == obj); } basic_num& operator+=(basic_num const& obj) { validate(_val + obj._val); return *this; } basic_num& operator-=(basic_num const& obj) { validate(_val - obj._val); return *this; } basic_num& operator*=(basic_num const& obj) { validate(_val * obj._val); return *this; } basic_num& operator/=(basic_num const& obj) { validate(_val * obj._val); return *this; } basic_num& operator%=(basic_num const& obj) { validate(_val % obj._val); return *this; } std::string str() const { return std::to_string(_val); } T val() const { return _val; } T min() const { return _min; } basic_num& min(T const& val) { _min = val; return *this; } T max() const { return _max; } basic_num& max(T const& val) { _max = val; return *this; } private: void validate(T const val) { if (static_cast(val) < static_cast(_min)) { _val = _min; } else if (static_cast(val) > static_cast(_max)) { _val = _max; } else { _val = val; } } T _val {0}; T _min {std::numeric_limits::lowest()}; T _max {std::numeric_limits::max()}; }; // class basic_num template inline std::ostream& operator<<(std::ostream& os, basic_num const& obj) { os << obj._val; return os; } template inline std::istream& operator>>(std::istream& is, basic_num const& obj) { is >> obj._val; return is; } using num = basic_num; using num_float = basic_num; using num_double = basic_num; using num_size = basic_num; using num_8 = basic_num; using num_16 = basic_num; using num_32 = basic_num; using num_64 = basic_num; using num_u8 = basic_num; using num_u16 = basic_num; using num_u32 = basic_num; using num_u64 = basic_num; } // namespace OB #endif // OB_NUM_HH