Make webrtc units division by integer constexpr
std::round is not constexpr until c++23 and force conversion to floating point which is unnecessary for integer devision
For integer division change rounding to 'round down' from 'round to nearest' as less surprising.
Bug: webrtc:13756
Change-Id: I9c2382bafc9ddccb0f54d6e7bf8cac4f2a3175a1
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/265863
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37250}
diff --git a/rtc_base/units/unit_base.h b/rtc_base/units/unit_base.h
index 0cd6a61..bbf7300 100644
--- a/rtc_base/units/unit_base.h
+++ b/rtc_base/units/unit_base.h
@@ -266,14 +266,18 @@
return UnitBase<Unit_T>::template ToValue<double>() /
other.template ToValue<double>();
}
- template <typename T>
- constexpr typename std::enable_if<std::is_arithmetic<T>::value, Unit_T>::type
- operator/(const T& scalar) const {
- return UnitBase<Unit_T>::FromValue(
- std::round(UnitBase<Unit_T>::template ToValue<int64_t>() / scalar));
+ template <typename T,
+ typename std::enable_if_t<std::is_floating_point_v<T>>* = nullptr>
+ Unit_T operator/(T scalar) const {
+ return UnitBase<Unit_T>::FromValue(std::llround(this->ToValue() / scalar));
}
- constexpr Unit_T operator*(double scalar) const {
- return UnitBase<Unit_T>::FromValue(std::round(this->ToValue() * scalar));
+ template <typename T,
+ typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
+ constexpr Unit_T operator/(T scalar) const {
+ return UnitBase<Unit_T>::FromValue(this->ToValue() / scalar);
+ }
+ Unit_T operator*(double scalar) const {
+ return UnitBase<Unit_T>::FromValue(std::llround(this->ToValue() * scalar));
}
constexpr Unit_T operator*(int64_t scalar) const {
return UnitBase<Unit_T>::FromValue(this->ToValue() * scalar);
diff --git a/rtc_base/units/unit_base_unittest.cc b/rtc_base/units/unit_base_unittest.cc
index 9eb0c33..258d7d1 100644
--- a/rtc_base/units/unit_base_unittest.cc
+++ b/rtc_base/units/unit_base_unittest.cc
@@ -68,6 +68,7 @@
static_assert(kTestUnitValue.ToValueOr(0) == kValue, "");
static_assert(TestUnitAddKilo(kTestUnitValue, 2).ToValue() == kValue + 2000,
"");
+ static_assert(TestUnit::FromValue(500) / 2 == TestUnit::FromValue(250));
}
TEST(UnitBaseTest, GetBackSameValues) {
@@ -216,6 +217,10 @@
EXPECT_EQ(mutable_delta, TestUnit::FromKilo(kValueA + kValueB));
mutable_delta -= TestUnit::FromKilo(kValueB);
EXPECT_EQ(mutable_delta, TestUnit::FromKilo(kValueA));
+
+ // Division by an int rounds towards zero to follow regular int division.
+ EXPECT_EQ(TestUnit::FromValue(789) / 10, TestUnit::FromValue(78));
+ EXPECT_EQ(TestUnit::FromValue(-789) / 10, TestUnit::FromValue(-78));
}
TEST(UnitBaseTest, InfinityOperations) {