Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(321)

Unified Diff: base/numerics/safe_math_impl.h

Issue 2612443002: Convert CheckedNumeric unary operators to constexpr (Closed)
Patch Set: docs Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/numerics/safe_math.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/numerics/safe_math_impl.h
diff --git a/base/numerics/safe_math_impl.h b/base/numerics/safe_math_impl.h
index 9a47a27a08139ba01c4f8794ab7e3a0194f9e961..7705daa41825ef5db0ee7ff385d96258035cd460 100644
--- a/base/numerics/safe_math_impl.h
+++ b/base/numerics/safe_math_impl.h
@@ -472,54 +472,6 @@ struct CheckedMinOp<
}
};
-template <typename T,
- typename std::enable_if<std::is_integral<T>::value &&
- std::is_signed<T>::value>::type* = nullptr>
-bool CheckedNeg(T value, T* result) {
- // The negation of signed min is min, so catch that one.
- if (value != std::numeric_limits<T>::lowest()) {
- *result = static_cast<T>(-value);
- return true;
- }
- return false;
-}
-
-template <typename T,
- typename std::enable_if<std::is_integral<T>::value &&
- !std::is_signed<T>::value>::type* = nullptr>
-bool CheckedNeg(T value, T* result) {
- if (!value) {
- *result = static_cast<T>(0);
- return true;
- }
- return false;
-}
-
-template <typename T,
- typename std::enable_if<std::is_integral<T>::value &&
- !std::is_signed<T>::value>::type* = nullptr>
-bool CheckedInv(T value, T* result) {
- *result = ~value;
- return true;
-}
-
-template <typename T,
- typename std::enable_if<std::is_integral<T>::value &&
- std::is_signed<T>::value>::type* = nullptr>
-bool CheckedAbs(T value, T* result) {
- *result = static_cast<T>(SafeUnsignedAbs(value));
- return *result != std::numeric_limits<T>::lowest();
-}
-
-template <typename T,
- typename std::enable_if<std::is_integral<T>::value &&
- !std::is_signed<T>::value>::type* = nullptr>
-bool CheckedAbs(T value, T* result) {
- // T is unsigned, so |value| must already be positive.
- *result = value;
- return true;
-}
-
// This is just boilerplate that wraps the standard floating point arithmetic.
// A macro isn't the nicest solution, but it beats rewriting these repeatedly.
#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \
@@ -544,20 +496,43 @@ BASE_FLOAT_ARITHMETIC_OPS(Div, /)
#undef BASE_FLOAT_ARITHMETIC_OPS
+// Wrap the unary operations to allow SFINAE when instantiating integrals versus
+// floating points. These don't perform any overflow checking. Rather, they
+// exhibit well-defined overflow semantics and rely on the caller to detect
+// if an overflow occured.
+
+template <typename T,
+ typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+constexpr T NegateWrapper(T value) {
+ using UnsignedT = typename std::make_unsigned<T>::type;
+ // This will compile to a NEG on Intel, and is normal negation on ARM.
+ return static_cast<T>(UnsignedT(0) - static_cast<UnsignedT>(value));
+}
+
template <
typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
-bool CheckedNeg(T value, T* result) {
- *result = static_cast<T>(-value);
- return true;
+constexpr T NegateWrapper(T value) {
+ return -value;
+}
+
+template <typename T,
+ typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+constexpr typename std::make_unsigned<T>::type InvertWrapper(T value) {
+ return ~value;
+}
+
+template <typename T,
+ typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
+constexpr T AbsWrapper(T value) {
+ return static_cast<T>(SafeUnsignedAbs(value));
}
template <
typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
-bool CheckedAbs(T value, T* result) {
- *result = static_cast<T>(std::abs(value));
- return true;
+constexpr T AbsWrapper(T value) {
+ return value < 0 ? -value : value;
}
// Floats carry around their validity state with them, but integers do not. So,
« no previous file with comments | « base/numerics/safe_math.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698