|
40 | 40 |
|
41 | 41 | namespace mozilla {
|
42 | 42 |
|
| 43 | +template<typename T> class CheckedInt; |
| 44 | + |
43 | 45 | namespace detail {
|
44 | 46 |
|
45 | 47 | /*
|
@@ -454,23 +456,32 @@ IsDivValid(T x, T y)
|
454 | 456 | !(IsSigned<T>::value && x == MinValue<T>::value && y == T(-1));
|
455 | 457 | }
|
456 | 458 |
|
457 |
| -// This is just to shut up msvc warnings about negating unsigned ints. |
458 |
| -template<typename T, bool IsTSigned = IsSigned<T>::value> |
459 |
| -struct OppositeIfSignedImpl |
460 |
| -{ |
461 |
| - static T run(T x) { return -x; } |
462 |
| -}; |
| 459 | +template<typename T, bool IsSigned = IsSigned<T>::value> |
| 460 | +struct NegateImpl; |
| 461 | + |
463 | 462 | template<typename T>
|
464 |
| -struct OppositeIfSignedImpl<T, false> |
| 463 | +struct NegateImpl<T, false> |
465 | 464 | {
|
466 |
| - static T run(T x) { return x; } |
| 465 | + static CheckedInt<T> negate(const CheckedInt<T>& val) |
| 466 | + { |
| 467 | + // Handle negation separately for signed/unsigned, for simpler code and to |
| 468 | + // avoid an MSVC warning negating an unsigned value. |
| 469 | + return CheckedInt<T>(0, val.isValid() && val.mValue == 0); |
| 470 | + } |
467 | 471 | };
|
| 472 | + |
468 | 473 | template<typename T>
|
469 |
| -inline T |
470 |
| -OppositeIfSigned(T x) |
| 474 | +struct NegateImpl<T, true> |
471 | 475 | {
|
472 |
| - return OppositeIfSignedImpl<T>::run(x); |
473 |
| -} |
| 476 | + static CheckedInt<T> negate(const CheckedInt<T>& val) |
| 477 | + { |
| 478 | + // Watch out for the min-value, which (with twos-complement) can't be |
| 479 | + // negated as -min-value is then (max-value + 1). |
| 480 | + if (!val.isValid() || val.mValue == MinValue<T>::value) |
| 481 | + return CheckedInt<T>(val.mValue, false); |
| 482 | + return CheckedInt<T>(-val.mValue, true); |
| 483 | + } |
| 484 | +}; |
474 | 485 |
|
475 | 486 | } // namespace detail
|
476 | 487 |
|
@@ -560,6 +571,8 @@ class CheckedInt
|
560 | 571 | "This type is not supported by CheckedInt");
|
561 | 572 | }
|
562 | 573 |
|
| 574 | + friend class detail::NegateImpl<T>; |
| 575 | + |
563 | 576 | public:
|
564 | 577 | /**
|
565 | 578 | * Constructs a checked integer with given @a value. The checked integer is
|
@@ -628,14 +641,7 @@ class CheckedInt
|
628 | 641 |
|
629 | 642 | CheckedInt operator -() const
|
630 | 643 | {
|
631 |
| - // Circumvent msvc warning about - applied to unsigned int. |
632 |
| - // if we're unsigned, the only valid case anyway is 0 |
633 |
| - // in which case - is a no-op. |
634 |
| - T result = detail::OppositeIfSigned(mValue); |
635 |
| - /* Help the compiler perform RVO (return value optimization). */ |
636 |
| - return CheckedInt(result, |
637 |
| - mIsValid && detail::IsSubValid(T(0), |
638 |
| - mValue)); |
| 644 | + return detail::NegateImpl<T>::negate(*this); |
639 | 645 | }
|
640 | 646 |
|
641 | 647 | /**
|
|
0 commit comments