| Index: base/numerics/safe_conversions.h
|
| diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h
|
| index b0ec279eb58551f9f792c18b43949951176083b3..c85e7c3114692954164d218e2c1690d9496f9fdf 100644
|
| --- a/base/numerics/safe_conversions.h
|
| +++ b/base/numerics/safe_conversions.h
|
| @@ -15,38 +15,6 @@
|
|
|
| namespace base {
|
|
|
| -// The following are helper constexpr template functions and classes for safely
|
| -// performing a range of conversions, assignments, and tests:
|
| -//
|
| -// checked_cast<> - Analogous to static_cast<> for numeric types, except
|
| -// that it CHECKs that the specified numeric conversion will not overflow
|
| -// or underflow. NaN source will always trigger a CHECK.
|
| -// The default CHECK triggers a crash, but the handler can be overriden.
|
| -// saturated_cast<> - Analogous to static_cast<> for numeric types, except
|
| -// that it returns a saturated result when the specified numeric conversion
|
| -// would otherwise overflow or underflow. An NaN source returns 0 by
|
| -// default, but can be overridden to return a different result.
|
| -// strict_cast<> - Analogous to static_cast<> for numeric types, except that
|
| -// it will cause a compile failure if the destination type is not large
|
| -// enough to contain any value in the source type. It performs no runtime
|
| -// checking and thus introduces no runtime overhead.
|
| -// IsValueInRangeForNumericType<>() - A convenience function that returns true
|
| -// if the type supplied to the template parameter can represent the value
|
| -// passed as an argument to the function.
|
| -// IsValueNegative<>() - A convenience function that will accept any arithmetic
|
| -// type as an argument and will return whether the value is less than zero.
|
| -// Unsigned types always return false.
|
| -// SafeUnsignedAbs() - Returns the absolute value of the supplied integer
|
| -// parameter as an unsigned result (thus avoiding an overflow if the value
|
| -// is the signed, two's complement minimum).
|
| -// StrictNumeric<> - A wrapper type that performs assignments and copies via
|
| -// the strict_cast<> template, and can perform valid arithmetic comparisons
|
| -// across any range of arithmetic types. StrictNumeric is the return type
|
| -// for values extracted from a CheckedNumeric class instance. The raw
|
| -// arithmetic value is extracted via static_cast to the underlying type.
|
| -// MakeStrictNum() - Creates a new StrictNumeric from the underlying type of
|
| -// the supplied arithmetic or StrictNumeric type.
|
| -
|
| // Convenience function that returns true if the supplied value is in range
|
| // for the destination type.
|
| template <typename Dst, typename Src>
|
| @@ -82,21 +50,47 @@ constexpr Dst checked_cast(Src value) {
|
| : CheckHandler::template HandleFailure<Dst>();
|
| }
|
|
|
| +// as_signed<> returns the supplied integral value (or integral castable
|
| +// Numeric template) cast as a signed integral of equivalent precision.
|
| +// I.e. it's mostly an alias for: static_cast<std::make_signed<T>::type>(t)
|
| +template <typename Src>
|
| +constexpr typename std::make_signed<
|
| + typename base::internal::UnderlyingType<Src>::type>::type
|
| +as_signed(const Src value) {
|
| + static_assert(std::is_integral<decltype(as_signed(value))>::value,
|
| + "Argument must be a signed or unsigned integer type.");
|
| + return static_cast<decltype(as_signed(value))>(value);
|
| +}
|
| +
|
| +// as_unsigned<> returns the supplied integral value (or integral castable
|
| +// Numeric template) cast as an unsigned integral of equivalent precision.
|
| +// I.e. it's mostly an alias for: static_cast<std::make_unsigned<T>::type>(t)
|
| +template <typename Src>
|
| +constexpr typename std::make_unsigned<
|
| + typename base::internal::UnderlyingType<Src>::type>::type
|
| +as_unsigned(const Src value) {
|
| + static_assert(std::is_integral<decltype(as_unsigned(value))>::value,
|
| + "Argument must be a signed or unsigned integer type.");
|
| + return static_cast<decltype(as_unsigned(value))>(value);
|
| +}
|
| +
|
| // Default boundaries for integral/float: max/infinity, lowest/-infinity, 0/NaN.
|
| +// You may provide your own limits (e.g. to saturated_cast) so long as you
|
| +// implement all of the static constexpr member functions in the class below.
|
| template <typename T>
|
| -struct SaturationDefaultHandler {
|
| +struct SaturationDefaultLimits : public std::numeric_limits<T> {
|
| static constexpr T NaN() {
|
| return std::numeric_limits<T>::has_quiet_NaN
|
| ? std::numeric_limits<T>::quiet_NaN()
|
| : T();
|
| }
|
| - static constexpr T max() { return std::numeric_limits<T>::max(); }
|
| + using std::numeric_limits<T>::max;
|
| static constexpr T Overflow() {
|
| return std::numeric_limits<T>::has_infinity
|
| ? std::numeric_limits<T>::infinity()
|
| : std::numeric_limits<T>::max();
|
| }
|
| - static constexpr T lowest() { return std::numeric_limits<T>::lowest(); }
|
| + using std::numeric_limits<T>::lowest;
|
| static constexpr T Underflow() {
|
| return std::numeric_limits<T>::has_infinity
|
| ? std::numeric_limits<T>::infinity() * -1
|
| @@ -124,8 +118,7 @@ constexpr Dst saturated_cast_impl(Src value, RangeCheck constraint) {
|
| // 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 = SaturationDefaultHandler,
|
| + template <typename> class SaturationHandler = SaturationDefaultLimits,
|
| typename Src>
|
| constexpr Dst saturated_cast(Src value) {
|
| using SrcType = typename UnderlyingType<Src>::type;
|
| @@ -238,24 +231,23 @@ std::ostream& operator<<(std::ostream& os, const StrictNumeric<T>& value) {
|
| return os;
|
| }
|
|
|
| -#define STRICT_COMPARISON_OP(NAME, OP) \
|
| - template <typename L, typename R, \
|
| - typename std::enable_if< \
|
| - internal::IsStrictOp<L, R>::value>::type* = nullptr> \
|
| - constexpr bool operator OP(const L lhs, const R rhs) { \
|
| - return SafeCompare<NAME, typename UnderlyingType<L>::type, \
|
| - typename UnderlyingType<R>::type>(lhs, rhs); \
|
| +#define BASE_NUMERIC_COMPARISON_OPERATORS(CLASS, NAME, OP) \
|
| + template <typename L, typename R, \
|
| + typename std::enable_if< \
|
| + internal::Is##CLASS##Op<L, R>::value>::type* = nullptr> \
|
| + constexpr bool operator OP(const L lhs, const R rhs) { \
|
| + return SafeCompare<NAME, typename UnderlyingType<L>::type, \
|
| + typename UnderlyingType<R>::type>(lhs, rhs); \
|
| }
|
|
|
| -STRICT_COMPARISON_OP(IsLess, <);
|
| -STRICT_COMPARISON_OP(IsLessOrEqual, <=);
|
| -STRICT_COMPARISON_OP(IsGreater, >);
|
| -STRICT_COMPARISON_OP(IsGreaterOrEqual, >=);
|
| -STRICT_COMPARISON_OP(IsEqual, ==);
|
| -STRICT_COMPARISON_OP(IsNotEqual, !=);
|
| +BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsLess, <);
|
| +BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsLessOrEqual, <=);
|
| +BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsGreater, >);
|
| +BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsGreaterOrEqual, >=);
|
| +BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsEqual, ==);
|
| +BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsNotEqual, !=);
|
|
|
| -#undef STRICT_COMPARISON_OP
|
| -};
|
| +}; // namespace internal
|
|
|
| using internal::strict_cast;
|
| using internal::saturated_cast;
|
|
|