Index: base/numerics/safe_math_impl.h |
diff --git a/base/numerics/safe_math_impl.h b/base/numerics/safe_math_impl.h |
index 08f2e88345f34d62870dcf16c569b126304f06f6..1bb5c5b83f2ee1f8ff39c7cc92976fb030dada6d 100644 |
--- a/base/numerics/safe_math_impl.h |
+++ b/base/numerics/safe_math_impl.h |
@@ -90,6 +90,25 @@ struct PositionOfSignBit { |
size_t>::type value = 8 * sizeof(Integer) - 1; |
}; |
+// This is used for UnsignedAbs, where we need to support floating-point |
+// template instantiations even though we don't actually support the operations. |
+// However, there is no corresponding implementation of e.g. CheckedUnsignedAbs, |
+// so the float versions will not compile. |
+template <typename Numeric, |
+ bool IsInteger = std::numeric_limits<Numeric>::is_integer, |
+ bool IsFloat = std::numeric_limits<Numeric>::is_iec559> |
+struct UnsignedOrFloatForSize; |
+ |
+template <typename Numeric> |
+struct UnsignedOrFloatForSize<Numeric, true, false> { |
+ typedef typename UnsignedIntegerForSize<Numeric>::type type; |
+}; |
+ |
+template <typename Numeric> |
+struct UnsignedOrFloatForSize<Numeric, false, true> { |
+ typedef Numeric type; |
+}; |
+ |
// Helper templates for integer manipulations. |
template <typename T> |
@@ -284,11 +303,31 @@ typename enable_if< |
std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, |
T>::type |
CheckedAbs(T value, RangeConstraint* validity) { |
- // Absolute value of a positive is just its identiy. |
+ // T is unsigned, so |value| must already be positive. |
*validity = RANGE_VALID; |
return value; |
} |
+template <typename T> |
+typename enable_if<std::numeric_limits<T>::is_integer && |
+ std::numeric_limits<T>::is_signed, |
+ typename UnsignedIntegerForSize<T>::type>::type |
+CheckedUnsignedAbs(T value) { |
+ typedef typename UnsignedIntegerForSize<T>::type UnsignedT; |
+ return value == std::numeric_limits<T>::min() |
+ ? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1 |
+ : static_cast<UnsignedT>(std::abs(value)); |
+} |
+ |
+template <typename T> |
+typename enable_if<std::numeric_limits<T>::is_integer && |
+ !std::numeric_limits<T>::is_signed, |
+ T>::type |
+CheckedUnsignedAbs(T value) { |
+ // T is unsigned, so |value| must already be positive. |
+ return value; |
+} |
+ |
// These are the floating point stubs that the compiler needs to see. Only the |
// negation operation is ever called. |
#define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ |