| Index: base/numerics/safe_math_impl.h
|
| diff --git a/base/numerics/safe_math_impl.h b/base/numerics/safe_math_impl.h
|
| index 7aab62dc52221b79d3959b682b0271a118915aa1..4b9877a386965cceda85a5c5c2a6f2b62186f235 100644
|
| --- a/base/numerics/safe_math_impl.h
|
| +++ b/base/numerics/safe_math_impl.h
|
| @@ -474,6 +474,46 @@ struct CheckedXorOp<T,
|
| }
|
| };
|
|
|
| +// Max doesn't really need to be implemented this way because it can't fail,
|
| +// but it makes the code much cleaner to use the MathOp wrappers.
|
| +template <typename T, typename U, class Enable = void>
|
| +struct CheckedMaxOp {};
|
| +
|
| +template <typename T, typename U>
|
| +struct CheckedMaxOp<
|
| + T,
|
| + U,
|
| + typename std::enable_if<std::is_arithmetic<T>::value &&
|
| + std::is_arithmetic<U>::value>::type> {
|
| + using result_type = typename MaxExponentPromotion<T, U>::type;
|
| + template <typename V = result_type>
|
| + static bool Do(T x, U y, V* result) {
|
| + *result = IsGreater<T, U>::Test(x, y) ? static_cast<result_type>(x)
|
| + : static_cast<result_type>(y);
|
| + return true;
|
| + }
|
| +};
|
| +
|
| +// Min doesn't really need to be implemented this way because it can't fail,
|
| +// but it makes the code much cleaner to use the MathOp wrappers.
|
| +template <typename T, typename U, class Enable = void>
|
| +struct CheckedMinOp {};
|
| +
|
| +template <typename T, typename U>
|
| +struct CheckedMinOp<
|
| + T,
|
| + U,
|
| + typename std::enable_if<std::is_arithmetic<T>::value &&
|
| + std::is_arithmetic<U>::value>::type> {
|
| + using result_type = typename LowestValuePromotion<T, U>::type;
|
| + template <typename V = result_type>
|
| + static bool Do(T x, U y, V* result) {
|
| + *result = IsLess<T, U>::Test(x, y) ? static_cast<result_type>(x)
|
| + : static_cast<result_type>(y);
|
| + return true;
|
| + }
|
| +};
|
| +
|
| template <typename T>
|
| typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
| std::numeric_limits<T>::is_signed,
|
| @@ -688,7 +728,12 @@ class CheckedNumericState<T, NUMERIC_FLOATING> {
|
| constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs)
|
| : value_(static_cast<T>(rhs.value())) {}
|
|
|
| - constexpr bool is_valid() const { return std::isfinite(value_); }
|
| + constexpr bool is_valid() const {
|
| + // Written this way because std::isfinite is not reliably constexpr.
|
| + // TODO(jschuh): Fix this if the libraries ever get fixed.
|
| + return value_ <= std::numeric_limits<T>::max() &&
|
| + value_ >= std::numeric_limits<T>::lowest();
|
| + }
|
| constexpr T value() const { return value_; }
|
| };
|
|
|
|
|