Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <limits>
- #include <iostream>
- using namespace std;
- struct overflow_exception {
- overflow_exception(string const& text) : message(text) { };
- string const& message_text() {
- return message;
- }
- private:
- string message;
- };
- struct signed_tag {};
- struct unsigned_tag {};
- template<typename T, bool C>
- struct overflow_traits;
- template<typename T>
- struct overflow_traits<T, 1> {
- typedef typename signed_tag tag;
- };
- template<typename T>
- struct overflow_traits<T, 0> {
- typedef typename unsigned_tag tag;
- };
- template<typename T>
- struct overflowChecking {
- overflowChecking() {};
- overflowChecking(T val) : value(val) {};
- //---------
- //add
- //---------
- overflowChecking<T> add_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, signed_tag) {
- if ((right.value < 0 && left.value < numeric_limits<T>::min() - right)
- || (right.value > 0 && left.value > numeric_limits<T>::max() - right)) {
- throw overflow_exception("signed numbers add overflow");
- }
- return overflowChecking<T>(left.value + right.value);
- }
- overflowChecking<T> add_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, unsigned_tag) {
- if (right.value > numeric_limits<T>::max() - left.value) {
- throw overflow_exception("unsigned numbers add overflow");
- }
- return overflowChecking<T>(left.value + right.value);
- }
- overflowChecking<T> operator+(overflowChecking<T> const& left, overflowChecking<T> const& right) {
- return add_impl(left, right, typename overflow_traits<T, numeric_limits<T>::is_signed()>::tag() tag);
- }
- //--------
- //sub
- //--------
- overflowChecking<T> sub_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, signed_tag) {
- if ((right.value > 0 && left.value < numeric_limits<T>::min() + right.value)
- || (right.value < 0 && left.value > numeric_limits<T>::max() + right.value)) {
- throw overflow_exception("signed numbers subtract overflow");
- }
- return overflowChecking<T>(left.value + right.value);
- }
- overflowChecking<T> sub_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, unsigned_tag) {
- if (right.value > left.value) {
- throw overflow_exception("unsigned numbers subtract overflow");
- }
- return overflowChecking<T>(left.value + right.value);
- }
- overflowChecking<T> operator-(overflowChecking<T> const& left, overflowChecking<T> const& right) {
- return sub_impl(left, right, typename overflow_traits<T, numeric_limits<T>::is_signed()>::tag() tag);
- }
- //--------
- //mul
- //--------
- overflowChecking<T> mul_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, signed_tag) {
- if (left.value != 0 && right.value != 0 && ((left.value == -1 && righ.value == numeric_limits<T>::min())
- || (right.value == -1 && left.value == numeric_limits<T>::min())
- || (right.value / abs(right.value) == left.value / abs(left.value) &&
- abs(right.value) > numeric_limits<T>::max() / abs(left.value))
- || (right.value / abs(right.value) != left.value / abs(left.value) &&
- right.value > numeric_limits<T>::min() / left.value))) {
- throw overflow_exception("singed numbers multiply overflow");
- }
- return overflowChecking<T>(left.value * right.value);
- }
- overflowChecking<T> mul_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, unsigned_tag) {
- if (left.value != 0 && right.value != 0 &&
- (left.value > numeric_limits<T>::max() / right.value)) {
- throw overflowChecking("unsigned numbers multiply overflow");
- }
- return overflowChecking<T>(left.value * right.value);
- }
- overflowChecking<T> operator*(overflowChecking<T> const& left, overflowChecking<T> const& right) {
- return mul_impl(left, right, typename overflow_traits<T, numeric_limits<T>::is_signed>::tag() tag);
- }
- //--------
- //div
- //--------
- overflowChecking<T> div_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, signed_tag) {
- if (right.value == -1 && left.value == numeric_limits<T>::min()) {
- throw overflow_exception("signed numbers division overflow");
- }
- return overflowChecking<T>(left.value / right.value);
- }
- overflowChecking<T> div_impl(overflowChecking<T> const& left, overflowChecking<T> const& right, unsigned_tag) {
- return overflowChecking(left.value / right.value);
- }
- overflowChecking<T> operator/(overflowChecking<T> const& left, overflowChecking<T> const& right) {
- return div_impl(left, right, typename overflow_traits<T, numeric_limits<T>::is_signed>::tag() tag);
- }
- overflowChecking<T>& operator=(overflowChecking<T> const& right) {
- this->value = right.value;
- return *this;
- }
- overflowChecking<T> negate(signed_tag) const {
- if (this->value == numeric_limits<T>::min()) {
- throw overflow_exception("signed number negate overflow");
- }
- this->value = this->value * (T)-1;
- return this->value;
- }
- overflowChecking<T> negate(unsigned_tag) const {
- throw overflow_exception("can't negate unsigned number");
- }
- overflowChecking<T> operator-() const {
- return this->negate(typename overflow_traits<T, numeric_limits<T>::is_signed>::tag() tag);
- }
- private:
- T value;
- };
- int main() {
- try {
- typedef int8_t type;
- {
- overflowChecking<type> v1(100);
- overflowChecking<type> v2(numeric_limits<type>::min());
- v1 + v2;
- v1 - v2;
- v1 * v2;
- v1 / v2;
- -v1;
- -v2;
- }
- }
- catch (overflow_exception& e) {
- cout << e.message_text();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement