Chromium Code Reviews| 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() && |
|
dcheng
2016/12/03 21:34:29
Out of curiosity, how come this used to work?
jschuh
2016/12/03 22:29:12
We didn't have any code tickling the constexpr pat
|
| + value_ >= std::numeric_limits<T>::lowest(); |
| + } |
| constexpr T value() const { return value_; } |
| }; |