Index: base/numerics/safe_conversions.h |
diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h |
index 66b278ff3d3e41b3ce33f1d56bea183f12dc7b61..99cbef4ca814c669514c0a206e6162458ed8c8e5 100644 |
--- a/base/numerics/safe_conversions.h |
+++ b/base/numerics/safe_conversions.h |
@@ -110,35 +110,35 @@ namespace internal { |
// that the specified numeric conversion will saturate by default rather than |
// overflow or underflow, and NaN assignment to an integral will return 0. |
// All boundary condition behaviors can be overriden with a custom handler. |
+template <template <typename> |
+ class SaturationHandler = SaturatedCastDefaultHandler, |
+ typename Dst, |
+ typename Src> |
+constexpr Dst saturated_cast_impl(const Src value, |
+ const RangeConstraint constraint) { |
+ return constraint.IsValid() |
+ ? static_cast<Dst>(value) |
+ : (constraint.IsOverflow() |
+ ? SaturationHandler<Dst>::HandleOverflow() |
+ // Skip this check for integral Src, which cannot be NaN. |
+ : (std::is_integral<Src>::value || constraint.IsUnderflow() |
+ ? SaturationHandler<Dst>::HandleUnderflow() |
+ : SaturationHandler<Dst>::HandleNaN())); |
+} |
+ |
+// saturated_cast<> is analogous to static_cast<> for numeric types, except |
+// that the specified numeric conversion will saturate by default rather than |
+// overflow or underflow, and NaN assignment to an integral will return 0. |
+// All boundary condition behaviors can be overriden with a custom handler. |
template <typename Dst, |
template <typename> |
class SaturationHandler = SaturatedCastDefaultHandler, |
typename Src> |
constexpr Dst saturated_cast(Src value) { |
- static_assert( |
- SaturationHandler<Dst>::lowest() < SaturationHandler<Dst>::max(), ""); |
- // While this looks like a lot of code, it's all constexpr and all but |
- // one variable are compile-time constants (enforced by a static_assert). |
- // So, it should evaluate to the minimum number of comparisons required |
- // for the range check, which is 0-3, depending on the exact source and |
- // destination types, and whatever custom range is specified. |
using SrcType = typename UnderlyingType<Src>::type; |
- return IsGreaterOrEqual<SrcType, Dst>::Test( |
- value, NarrowingRange<Dst, SrcType, SaturationHandler>::lowest()) |
- ? (IsLessOrEqual<SrcType, Dst>::Test( |
- value, |
- NarrowingRange<Dst, SrcType, SaturationHandler>::max()) |
- ? static_cast<Dst>(value) |
- : SaturationHandler<Dst>::HandleOverflow()) |
- // This last branch is a little confusing. It's specifically to |
- // catch NaN when converting from float to integral. |
- : (std::is_integral<SrcType>::value || |
- std::is_floating_point<Dst>::value || |
- IsLessOrEqual<SrcType, Dst>::Test( |
- value, NarrowingRange<Dst, SrcType, |
- SaturationHandler>::max()) |
- ? SaturationHandler<Dst>::HandleUnderflow() |
- : SaturationHandler<Dst>::HandleNaN()); |
+ return saturated_cast_impl<SaturationHandler, Dst>( |
+ static_cast<SrcType>(value), |
+ DstRangeRelationToSrcRange<Dst, SaturationHandler, SrcType>(value)); |
} |
// strict_cast<> is analogous to static_cast<> for numeric types, except that |