// // limit.h // utilities // // Created by Sam Jaffe on 10/22/13. // Copyright (c) 2013 Sam Jaffe. All rights reserved. // #pragma once #include #include namespace math { struct { } assert_bounds; using AssertBounds = decltype(assert_bounds); template class Bound final { public: static_assert(MINIMUM_VALUE <= MAXIMUM_VALUE, "The minimum value must be less than or equal to the maximum"); using value_type = T; using underlying_type = value_type; static constexpr const value_type min = MINIMUM_VALUE; static constexpr const value_type max = MAXIMUM_VALUE; private: value_type value{min}; public: constexpr Bound() = default; constexpr Bound(value_type const & val) noexcept : value(clamp(val, min, max)) {} Bound(AssertBounds, value_type val) : value(val) { if (val < min || max < val) { throw std::out_of_range{"Must construct a value within range"}; } } Bound & operator-=(value_type by) { return *this = Bound(value - by); } Bound & operator+=(value_type by) { return *this = Bound(value + by); } Bound operator+(value_type by) const { return Bound{*this} += by; } Bound operator-(value_type by) const { return Bound{*this} -= by; } Bound & operator--() { return *this -= 1; } Bound & operator++() { return *this += 1; } Bound operator--(int) { Bound tmp = *this; operator--(); return tmp; } Bound operator++(int) { Bound tmp = *this; operator++(); return tmp; } operator value_type() const { return value; } }; template using SymBound = Bound; template using UniBound = std::conditional_t<0 <= VAL, Bound, Bound>; template auto operator+(Bound lhs, Bound rhs) { return L(lhs) + R(rhs); } template auto operator-(Bound lhs, Bound rhs) { return L(lhs) - R(rhs); } template auto operator*(Bound lhs, Bound rhs) { return L(lhs) * R(rhs); } template auto operator/(Bound lhs, Bound rhs) { return L(lhs) / R(rhs); } }