diff --git a/rtc_base/numerics/safe_conversions.h b/rtc_base/numerics/safe_conversions.h index 58efcaa746..5d58672510 100644 --- a/rtc_base/numerics/safe_conversions.h +++ b/rtc_base/numerics/safe_conversions.h @@ -23,7 +23,7 @@ namespace rtc { // Convenience function that returns true if the supplied value is in range // for the destination type. template -inline bool IsValueInRangeForNumericType(Src value) { +inline constexpr bool IsValueInRangeForNumericType(Src value) { return internal::RangeCheck(value) == internal::TYPE_VALID; } @@ -32,12 +32,12 @@ inline bool IsValueInRangeForNumericType(Src value) { // conversion will not overflow or underflow. NaN source will always trigger // the [D]CHECK. template -inline Dst checked_cast(Src value) { +inline constexpr Dst checked_cast(Src value) { RTC_CHECK(IsValueInRangeForNumericType(value)); return static_cast(value); } template -inline Dst dchecked_cast(Src value) { +inline constexpr Dst dchecked_cast(Src value) { RTC_DCHECK(IsValueInRangeForNumericType(value)); return static_cast(value); } @@ -46,7 +46,7 @@ inline Dst dchecked_cast(Src value) { // that the specified numeric conversion will saturate rather than overflow or // underflow. NaN assignment to an integral will trigger a RTC_CHECK condition. template -inline Dst saturated_cast(Src value) { +inline constexpr Dst saturated_cast(Src value) { // Optimization for floating point values, which already saturate. if (std::numeric_limits::is_iec559) return static_cast(value); diff --git a/rtc_base/numerics/safe_conversions_impl.h b/rtc_base/numerics/safe_conversions_impl.h index 9b4f1c6483..e924ce3256 100644 --- a/rtc_base/numerics/safe_conversions_impl.h +++ b/rtc_base/numerics/safe_conversions_impl.h @@ -101,13 +101,13 @@ struct RangeCheckImpl {}; // Dst range always contains the result: nothing to check. template struct RangeCheckImpl { - static RangeCheckResult Check(Src value) { return TYPE_VALID; } + static constexpr RangeCheckResult Check(Src value) { return TYPE_VALID; } }; // Signed to signed narrowing. template struct RangeCheckImpl { - static RangeCheckResult Check(Src value) { + static constexpr RangeCheckResult Check(Src value) { typedef std::numeric_limits DstLimits; return DstLimits::is_iec559 ? BASE_NUMERIC_RANGE_CHECK_RESULT( @@ -122,7 +122,7 @@ struct RangeCheckImpl { // Unsigned to unsigned narrowing. template struct RangeCheckImpl { - static RangeCheckResult Check(Src value) { + static constexpr RangeCheckResult Check(Src value) { typedef std::numeric_limits DstLimits; return BASE_NUMERIC_RANGE_CHECK_RESULT( value <= static_cast(DstLimits::max()), true); @@ -132,7 +132,7 @@ struct RangeCheckImpl { // Unsigned to signed. template struct RangeCheckImpl { - static RangeCheckResult Check(Src value) { + static constexpr RangeCheckResult Check(Src value) { typedef std::numeric_limits DstLimits; return sizeof(Dst) > sizeof(Src) ? TYPE_VALID @@ -144,14 +144,16 @@ struct RangeCheckImpl { // Signed to unsigned. template struct RangeCheckImpl { - static RangeCheckResult Check(Src value) { - typedef std::numeric_limits DstLimits; - typedef std::numeric_limits SrcLimits; - // Compare based on max_exponent, which we must compute for integrals. - static const size_t kDstMaxExponent = sizeof(Dst) * 8; - static const size_t kSrcMaxExponent = - SrcLimits::is_iec559 ? SrcLimits::max_exponent : (sizeof(Src) * 8 - 1); - return (kDstMaxExponent >= kSrcMaxExponent) + typedef std::numeric_limits DstLimits; + typedef std::numeric_limits SrcLimits; + // Compare based on max_exponent, which we must compute for integrals. + static constexpr size_t DstMaxExponent() { return sizeof(Dst) * 8; } + static constexpr size_t SrcMaxExponent() { + return SrcLimits::is_iec559 ? SrcLimits::max_exponent + : (sizeof(Src) * 8 - 1); + } + static constexpr RangeCheckResult Check(Src value) { + return (DstMaxExponent() >= SrcMaxExponent()) ? BASE_NUMERIC_RANGE_CHECK_RESULT(true, value >= static_cast(0)) : BASE_NUMERIC_RANGE_CHECK_RESULT( @@ -161,7 +163,7 @@ struct RangeCheckImpl { }; template -inline RangeCheckResult RangeCheck(Src value) { +inline constexpr RangeCheckResult RangeCheck(Src value) { static_assert(std::numeric_limits::is_specialized, "argument must be numeric"); static_assert(std::numeric_limits::is_specialized,