Makes all units and operations constexpr

Since RTC_DCHECK was made constexpr compatible, we can now
make the unit classes fully constexpr.

Bug: webrtc:9883
Change-Id: I18973c2f318449869cf0bd45699c41be53fba806
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/167722
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Ali Tofigh <alito@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30403}
This commit is contained in:
Sebastian Jansson
2020-01-29 10:44:51 +01:00
committed by Commit Bot
parent 48be482d73
commit d7fade5738
8 changed files with 79 additions and 65 deletions

View File

@ -65,7 +65,7 @@ class DataRate final : public rtc_units_impl::RelativeUnit<DataRate> {
return ToFraction<8, T>(); return ToFraction<8, T>();
} }
template <typename T = int64_t> template <typename T = int64_t>
T kbps() const { constexpr T kbps() const {
return ToFraction<1000, T>(); return ToFraction<1000, T>();
} }
constexpr int64_t bps_or(int64_t fallback_value) const { constexpr int64_t bps_or(int64_t fallback_value) const {
@ -84,7 +84,7 @@ class DataRate final : public rtc_units_impl::RelativeUnit<DataRate> {
}; };
namespace data_rate_impl { namespace data_rate_impl {
inline int64_t Microbits(const DataSize& size) { inline constexpr int64_t Microbits(const DataSize& size) {
constexpr int64_t kMaxBeforeConversion = constexpr int64_t kMaxBeforeConversion =
std::numeric_limits<int64_t>::max() / 8000000; std::numeric_limits<int64_t>::max() / 8000000;
RTC_DCHECK_LE(size.bytes(), kMaxBeforeConversion) RTC_DCHECK_LE(size.bytes(), kMaxBeforeConversion)
@ -92,7 +92,7 @@ inline int64_t Microbits(const DataSize& size) {
return size.bytes() * 8000000; return size.bytes() * 8000000;
} }
inline int64_t MillibytePerSec(const DataRate& size) { inline constexpr int64_t MillibytePerSec(const DataRate& size) {
constexpr int64_t kMaxBeforeConversion = constexpr int64_t kMaxBeforeConversion =
std::numeric_limits<int64_t>::max() / (1000 / 8); std::numeric_limits<int64_t>::max() / (1000 / 8);
RTC_DCHECK_LE(size.bps(), kMaxBeforeConversion) RTC_DCHECK_LE(size.bps(), kMaxBeforeConversion)
@ -101,31 +101,36 @@ inline int64_t MillibytePerSec(const DataRate& size) {
} }
} // namespace data_rate_impl } // namespace data_rate_impl
inline DataRate operator/(const DataSize size, const TimeDelta duration) { inline constexpr DataRate operator/(const DataSize size,
const TimeDelta duration) {
return DataRate::bps(data_rate_impl::Microbits(size) / duration.us()); return DataRate::bps(data_rate_impl::Microbits(size) / duration.us());
} }
inline TimeDelta operator/(const DataSize size, const DataRate rate) { inline constexpr TimeDelta operator/(const DataSize size, const DataRate rate) {
return TimeDelta::us(data_rate_impl::Microbits(size) / rate.bps()); return TimeDelta::us(data_rate_impl::Microbits(size) / rate.bps());
} }
inline DataSize operator*(const DataRate rate, const TimeDelta duration) { inline constexpr DataSize operator*(const DataRate rate,
const TimeDelta duration) {
int64_t microbits = rate.bps() * duration.us(); int64_t microbits = rate.bps() * duration.us();
return DataSize::bytes((microbits + 4000000) / 8000000); return DataSize::bytes((microbits + 4000000) / 8000000);
} }
inline DataSize operator*(const TimeDelta duration, const DataRate rate) { inline constexpr DataSize operator*(const TimeDelta duration,
const DataRate rate) {
return rate * duration; return rate * duration;
} }
inline DataSize operator/(const DataRate rate, const Frequency frequency) { inline constexpr DataSize operator/(const DataRate rate,
const Frequency frequency) {
int64_t millihertz = frequency.millihertz<int64_t>(); int64_t millihertz = frequency.millihertz<int64_t>();
// Note that the value is truncated here reather than rounded, potentially // Note that the value is truncated here reather than rounded, potentially
// introducing an error of .5 bytes if rounding were expected. // introducing an error of .5 bytes if rounding were expected.
return DataSize::bytes(data_rate_impl::MillibytePerSec(rate) / millihertz); return DataSize::bytes(data_rate_impl::MillibytePerSec(rate) / millihertz);
} }
inline Frequency operator/(const DataRate rate, const DataSize size) { inline constexpr Frequency operator/(const DataRate rate, const DataSize size) {
return Frequency::millihertz(data_rate_impl::MillibytePerSec(rate) / return Frequency::millihertz(data_rate_impl::MillibytePerSec(rate) /
size.bytes()); size.bytes());
} }
inline DataRate operator*(const DataSize size, const Frequency frequency) { inline constexpr DataRate operator*(const DataSize size,
const Frequency frequency) {
RTC_DCHECK(frequency.IsZero() || RTC_DCHECK(frequency.IsZero() ||
size.bytes() <= std::numeric_limits<int64_t>::max() / 8 / size.bytes() <= std::numeric_limits<int64_t>::max() / 8 /
frequency.millihertz<int64_t>()); frequency.millihertz<int64_t>());
@ -133,7 +138,8 @@ inline DataRate operator*(const DataSize size, const Frequency frequency) {
size.bytes() * 8 * frequency.millihertz<int64_t>(); size.bytes() * 8 * frequency.millihertz<int64_t>();
return DataRate::bps((millibits_per_second + 500) / 1000); return DataRate::bps((millibits_per_second + 500) / 1000);
} }
inline DataRate operator*(const Frequency frequency, const DataSize size) { inline constexpr DataRate operator*(const Frequency frequency,
const DataSize size) {
return size * frequency; return size * frequency;
} }

View File

@ -32,12 +32,12 @@ class DataSize final : public rtc_units_impl::RelativeUnit<DataSize> {
} }
template <typename T> template <typename T>
static DataSize bytes(T bytes) { static constexpr DataSize bytes(T bytes) {
static_assert(std::is_arithmetic<T>::value, ""); static_assert(std::is_arithmetic<T>::value, "");
return FromValue(bytes); return FromValue(bytes);
} }
template <typename T = int64_t> template <typename T = int64_t>
T bytes() const { constexpr T bytes() const {
return ToValue<T>(); return ToValue<T>();
} }

View File

@ -32,21 +32,21 @@ class Frequency final : public rtc_units_impl::RelativeUnit<Frequency> {
return FromFraction(1000, hertz); return FromFraction(1000, hertz);
} }
template <typename T> template <typename T>
static Frequency hertz(T hertz) { static constexpr Frequency hertz(T hertz) {
static_assert(std::is_arithmetic<T>::value, ""); static_assert(std::is_arithmetic<T>::value, "");
return FromFraction(1000, hertz); return FromFraction(1000, hertz);
} }
template <typename T> template <typename T>
static Frequency millihertz(T hertz) { static constexpr Frequency millihertz(T hertz) {
static_assert(std::is_arithmetic<T>::value, ""); static_assert(std::is_arithmetic<T>::value, "");
return FromValue(hertz); return FromValue(hertz);
} }
template <typename T = int64_t> template <typename T = int64_t>
T hertz() const { constexpr T hertz() const {
return ToFraction<1000, T>(); return ToFraction<1000, T>();
} }
template <typename T = int64_t> template <typename T = int64_t>
T millihertz() const { constexpr T millihertz() const {
return ToValue<T>(); return ToValue<T>();
} }
@ -56,7 +56,8 @@ class Frequency final : public rtc_units_impl::RelativeUnit<Frequency> {
static constexpr bool one_sided = true; static constexpr bool one_sided = true;
}; };
inline Frequency operator/(int64_t nominator, const TimeDelta& interval) { inline constexpr Frequency operator/(int64_t nominator,
const TimeDelta& interval) {
constexpr int64_t kKiloPerMicro = 1000 * 1000000; constexpr int64_t kKiloPerMicro = 1000 * 1000000;
RTC_DCHECK_LE(nominator, std::numeric_limits<int64_t>::max() / kKiloPerMicro); RTC_DCHECK_LE(nominator, std::numeric_limits<int64_t>::max() / kKiloPerMicro);
RTC_CHECK(interval.IsFinite()); RTC_CHECK(interval.IsFinite());
@ -64,7 +65,8 @@ inline Frequency operator/(int64_t nominator, const TimeDelta& interval) {
return Frequency::millihertz(nominator * kKiloPerMicro / interval.us()); return Frequency::millihertz(nominator * kKiloPerMicro / interval.us());
} }
inline TimeDelta operator/(int64_t nominator, const Frequency& frequency) { inline constexpr TimeDelta operator/(int64_t nominator,
const Frequency& frequency) {
constexpr int64_t kMegaPerMilli = 1000000 * 1000; constexpr int64_t kMegaPerMilli = 1000000 * 1000;
RTC_DCHECK_LE(nominator, std::numeric_limits<int64_t>::max() / kMegaPerMilli); RTC_DCHECK_LE(nominator, std::numeric_limits<int64_t>::max() / kMegaPerMilli);
RTC_CHECK(frequency.IsFinite()); RTC_CHECK(frequency.IsFinite());

View File

@ -46,34 +46,34 @@ class TimeDelta final : public rtc_units_impl::RelativeUnit<TimeDelta> {
return FromValue(us); return FromValue(us);
} }
template <typename T> template <typename T>
static TimeDelta seconds(T seconds) { static constexpr TimeDelta seconds(T seconds) {
static_assert(std::is_arithmetic<T>::value, ""); static_assert(std::is_arithmetic<T>::value, "");
return FromFraction(1'000'000, seconds); return FromFraction(1'000'000, seconds);
} }
template <typename T> template <typename T>
static TimeDelta ms(T milliseconds) { static constexpr TimeDelta ms(T milliseconds) {
static_assert(std::is_arithmetic<T>::value, ""); static_assert(std::is_arithmetic<T>::value, "");
return FromFraction(1000, milliseconds); return FromFraction(1000, milliseconds);
} }
template <typename T> template <typename T>
static TimeDelta us(T microseconds) { static constexpr TimeDelta us(T microseconds) {
static_assert(std::is_arithmetic<T>::value, ""); static_assert(std::is_arithmetic<T>::value, "");
return FromValue(microseconds); return FromValue(microseconds);
} }
template <typename T = int64_t> template <typename T = int64_t>
T seconds() const { constexpr T seconds() const {
return ToFraction<1000000, T>(); return ToFraction<1000000, T>();
} }
template <typename T = int64_t> template <typename T = int64_t>
T ms() const { constexpr T ms() const {
return ToFraction<1000, T>(); return ToFraction<1000, T>();
} }
template <typename T = int64_t> template <typename T = int64_t>
T us() const { constexpr T us() const {
return ToValue<T>(); return ToValue<T>();
} }
template <typename T = int64_t> template <typename T = int64_t>
T ns() const { constexpr T ns() const {
return ToMultiple<1000, T>(); return ToMultiple<1000, T>();
} }
@ -87,7 +87,9 @@ class TimeDelta final : public rtc_units_impl::RelativeUnit<TimeDelta> {
return ToValueOr(fallback_value); return ToValueOr(fallback_value);
} }
TimeDelta Abs() const { return TimeDelta::us(std::abs(us())); } constexpr TimeDelta Abs() const {
return us() < 0 ? TimeDelta::us(-us()) : *this;
}
private: private:
friend class rtc_units_impl::UnitBase<TimeDelta>; friend class rtc_units_impl::UnitBase<TimeDelta>;

View File

@ -44,30 +44,30 @@ class Timestamp final : public rtc_units_impl::UnitBase<Timestamp> {
} }
template <typename T> template <typename T>
static Timestamp seconds(T seconds) { static constexpr Timestamp seconds(T seconds) {
static_assert(std::is_arithmetic<T>::value, ""); static_assert(std::is_arithmetic<T>::value, "");
return FromFraction(1'000'000, seconds); return FromFraction(1'000'000, seconds);
} }
template <typename T> template <typename T>
static Timestamp ms(T milliseconds) { static constexpr Timestamp ms(T milliseconds) {
static_assert(std::is_arithmetic<T>::value, ""); static_assert(std::is_arithmetic<T>::value, "");
return FromFraction(1000, milliseconds); return FromFraction(1000, milliseconds);
} }
template <typename T> template <typename T>
static Timestamp us(T microseconds) { static constexpr Timestamp us(T microseconds) {
static_assert(std::is_arithmetic<T>::value, ""); static_assert(std::is_arithmetic<T>::value, "");
return FromValue(microseconds); return FromValue(microseconds);
} }
template <typename T = int64_t> template <typename T = int64_t>
T seconds() const { constexpr T seconds() const {
return ToFraction<1000000, T>(); return ToFraction<1000000, T>();
} }
template <typename T = int64_t> template <typename T = int64_t>
T ms() const { constexpr T ms() const {
return ToFraction<1000, T>(); return ToFraction<1000, T>();
} }
template <typename T = int64_t> template <typename T = int64_t>
T us() const { constexpr T us() const {
return ToValue<T>(); return ToValue<T>();
} }
@ -81,7 +81,7 @@ class Timestamp final : public rtc_units_impl::UnitBase<Timestamp> {
return ToValueOr(fallback_value); return ToValueOr(fallback_value);
} }
Timestamp operator+(const TimeDelta delta) const { constexpr Timestamp operator+(const TimeDelta delta) const {
if (IsPlusInfinity() || delta.IsPlusInfinity()) { if (IsPlusInfinity() || delta.IsPlusInfinity()) {
RTC_DCHECK(!IsMinusInfinity()); RTC_DCHECK(!IsMinusInfinity());
RTC_DCHECK(!delta.IsMinusInfinity()); RTC_DCHECK(!delta.IsMinusInfinity());
@ -93,7 +93,7 @@ class Timestamp final : public rtc_units_impl::UnitBase<Timestamp> {
} }
return Timestamp::us(us() + delta.us()); return Timestamp::us(us() + delta.us());
} }
Timestamp operator-(const TimeDelta delta) const { constexpr Timestamp operator-(const TimeDelta delta) const {
if (IsPlusInfinity() || delta.IsMinusInfinity()) { if (IsPlusInfinity() || delta.IsMinusInfinity()) {
RTC_DCHECK(!IsMinusInfinity()); RTC_DCHECK(!IsMinusInfinity());
RTC_DCHECK(!delta.IsPlusInfinity()); RTC_DCHECK(!delta.IsPlusInfinity());
@ -105,7 +105,7 @@ class Timestamp final : public rtc_units_impl::UnitBase<Timestamp> {
} }
return Timestamp::us(us() - delta.us()); return Timestamp::us(us() - delta.us());
} }
TimeDelta operator-(const Timestamp other) const { constexpr TimeDelta operator-(const Timestamp other) const {
if (IsPlusInfinity() || other.IsMinusInfinity()) { if (IsPlusInfinity() || other.IsMinusInfinity()) {
RTC_DCHECK(!IsMinusInfinity()); RTC_DCHECK(!IsMinusInfinity());
RTC_DCHECK(!other.IsPlusInfinity()); RTC_DCHECK(!other.IsPlusInfinity());
@ -117,11 +117,11 @@ class Timestamp final : public rtc_units_impl::UnitBase<Timestamp> {
} }
return TimeDelta::us(us() - other.us()); return TimeDelta::us(us() - other.us());
} }
Timestamp& operator-=(const TimeDelta delta) { constexpr Timestamp& operator-=(const TimeDelta delta) {
*this = *this - delta; *this = *this - delta;
return *this; return *this;
} }
Timestamp& operator+=(const TimeDelta delta) { constexpr Timestamp& operator+=(const TimeDelta delta) {
*this = *this + delta; *this = *this + delta;
return *this; return *this;
} }

View File

@ -68,21 +68,21 @@ class UnitBase {
constexpr bool operator<(const Unit_T& other) const { constexpr bool operator<(const Unit_T& other) const {
return value_ < other.value_; return value_ < other.value_;
} }
Unit_T RoundTo(const Unit_T& resolution) const { constexpr Unit_T RoundTo(const Unit_T& resolution) const {
RTC_DCHECK(IsFinite()); RTC_DCHECK(IsFinite());
RTC_DCHECK(resolution.IsFinite()); RTC_DCHECK(resolution.IsFinite());
RTC_DCHECK_GT(resolution.value_, 0); RTC_DCHECK_GT(resolution.value_, 0);
return Unit_T((value_ + resolution.value_ / 2) / resolution.value_) * return Unit_T((value_ + resolution.value_ / 2) / resolution.value_) *
resolution.value_; resolution.value_;
} }
Unit_T RoundUpTo(const Unit_T& resolution) const { constexpr Unit_T RoundUpTo(const Unit_T& resolution) const {
RTC_DCHECK(IsFinite()); RTC_DCHECK(IsFinite());
RTC_DCHECK(resolution.IsFinite()); RTC_DCHECK(resolution.IsFinite());
RTC_DCHECK_GT(resolution.value_, 0); RTC_DCHECK_GT(resolution.value_, 0);
return Unit_T((value_ + resolution.value_ - 1) / resolution.value_) * return Unit_T((value_ + resolution.value_ - 1) / resolution.value_) *
resolution.value_; resolution.value_;
} }
Unit_T RoundDownTo(const Unit_T& resolution) const { constexpr Unit_T RoundDownTo(const Unit_T& resolution) const {
RTC_DCHECK(IsFinite()); RTC_DCHECK(IsFinite());
RTC_DCHECK(resolution.IsFinite()); RTC_DCHECK(resolution.IsFinite());
RTC_DCHECK_GT(resolution.value_, 0); RTC_DCHECK_GT(resolution.value_, 0);
@ -132,7 +132,8 @@ class UnitBase {
} }
template <typename T = int64_t> template <typename T = int64_t>
typename std::enable_if<std::is_integral<T>::value, T>::type ToValue() const { constexpr typename std::enable_if<std::is_integral<T>::value, T>::type
ToValue() const {
RTC_DCHECK(IsFinite()); RTC_DCHECK(IsFinite());
return rtc::dchecked_cast<T>(value_); return rtc::dchecked_cast<T>(value_);
} }
@ -150,8 +151,8 @@ class UnitBase {
} }
template <int64_t Denominator, typename T = int64_t> template <int64_t Denominator, typename T = int64_t>
typename std::enable_if<std::is_integral<T>::value, T>::type ToFraction() constexpr typename std::enable_if<std::is_integral<T>::value, T>::type
const { ToFraction() const {
RTC_DCHECK(IsFinite()); RTC_DCHECK(IsFinite());
if (Unit_T::one_sided) { if (Unit_T::one_sided) {
return rtc::dchecked_cast<T>( return rtc::dchecked_cast<T>(
@ -175,8 +176,8 @@ class UnitBase {
} }
template <int64_t Factor, typename T = int64_t> template <int64_t Factor, typename T = int64_t>
typename std::enable_if<std::is_integral<T>::value, T>::type ToMultiple() constexpr typename std::enable_if<std::is_integral<T>::value, T>::type
const { ToMultiple() const {
RTC_DCHECK_GE(ToValue(), std::numeric_limits<T>::min() / Factor); RTC_DCHECK_GE(ToValue(), std::numeric_limits<T>::min() / Factor);
RTC_DCHECK_LE(ToValue(), std::numeric_limits<T>::max() / Factor); RTC_DCHECK_LE(ToValue(), std::numeric_limits<T>::max() / Factor);
return rtc::dchecked_cast<T>(ToValue() * Factor); return rtc::dchecked_cast<T>(ToValue() * Factor);
@ -200,9 +201,9 @@ class UnitBase {
return std::numeric_limits<int64_t>::min(); return std::numeric_limits<int64_t>::min();
} }
Unit_T& AsSubClassRef() { return reinterpret_cast<Unit_T&>(*this); } constexpr Unit_T& AsSubClassRef() { return static_cast<Unit_T&>(*this); }
constexpr const Unit_T& AsSubClassRef() const { constexpr const Unit_T& AsSubClassRef() const {
return reinterpret_cast<const Unit_T&>(*this); return static_cast<const Unit_T&>(*this);
} }
// Assumes that n >= 0 and d > 0. // Assumes that n >= 0 and d > 0.
static constexpr int64_t DivRoundPositiveToNearest(int64_t n, int64_t d) { static constexpr int64_t DivRoundPositiveToNearest(int64_t n, int64_t d) {
@ -222,14 +223,14 @@ class UnitBase {
template <class Unit_T> template <class Unit_T>
class RelativeUnit : public UnitBase<Unit_T> { class RelativeUnit : public UnitBase<Unit_T> {
public: public:
Unit_T Clamped(Unit_T min_value, Unit_T max_value) const { constexpr Unit_T Clamped(Unit_T min_value, Unit_T max_value) const {
return std::max(min_value, return std::max(min_value,
std::min(UnitBase<Unit_T>::AsSubClassRef(), max_value)); std::min(UnitBase<Unit_T>::AsSubClassRef(), max_value));
} }
void Clamp(Unit_T min_value, Unit_T max_value) { constexpr void Clamp(Unit_T min_value, Unit_T max_value) {
*this = Clamped(min_value, max_value); *this = Clamped(min_value, max_value);
} }
Unit_T operator+(const Unit_T other) const { constexpr Unit_T operator+(const Unit_T other) const {
if (this->IsPlusInfinity() || other.IsPlusInfinity()) { if (this->IsPlusInfinity() || other.IsPlusInfinity()) {
RTC_DCHECK(!this->IsMinusInfinity()); RTC_DCHECK(!this->IsMinusInfinity());
RTC_DCHECK(!other.IsMinusInfinity()); RTC_DCHECK(!other.IsMinusInfinity());
@ -241,7 +242,7 @@ class RelativeUnit : public UnitBase<Unit_T> {
} }
return UnitBase<Unit_T>::FromValue(this->ToValue() + other.ToValue()); return UnitBase<Unit_T>::FromValue(this->ToValue() + other.ToValue());
} }
Unit_T operator-(const Unit_T other) const { constexpr Unit_T operator-(const Unit_T other) const {
if (this->IsPlusInfinity() || other.IsMinusInfinity()) { if (this->IsPlusInfinity() || other.IsMinusInfinity()) {
RTC_DCHECK(!this->IsMinusInfinity()); RTC_DCHECK(!this->IsMinusInfinity());
RTC_DCHECK(!other.IsPlusInfinity()); RTC_DCHECK(!other.IsPlusInfinity());
@ -253,11 +254,11 @@ class RelativeUnit : public UnitBase<Unit_T> {
} }
return UnitBase<Unit_T>::FromValue(this->ToValue() - other.ToValue()); return UnitBase<Unit_T>::FromValue(this->ToValue() - other.ToValue());
} }
Unit_T& operator+=(const Unit_T other) { constexpr Unit_T& operator+=(const Unit_T other) {
*this = *this + other; *this = *this + other;
return this->AsSubClassRef(); return this->AsSubClassRef();
} }
Unit_T& operator-=(const Unit_T other) { constexpr Unit_T& operator-=(const Unit_T other) {
*this = *this - other; *this = *this - other;
return this->AsSubClassRef(); return this->AsSubClassRef();
} }
@ -266,18 +267,18 @@ class RelativeUnit : public UnitBase<Unit_T> {
other.template ToValue<double>(); other.template ToValue<double>();
} }
template <typename T> template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, Unit_T>::type operator/( constexpr typename std::enable_if<std::is_arithmetic<T>::value, Unit_T>::type
const T& scalar) const { operator/(const T& scalar) const {
return UnitBase<Unit_T>::FromValue( return UnitBase<Unit_T>::FromValue(
std::round(UnitBase<Unit_T>::template ToValue<int64_t>() / scalar)); std::round(UnitBase<Unit_T>::template ToValue<int64_t>() / scalar));
} }
Unit_T operator*(const double scalar) const { constexpr Unit_T operator*(double scalar) const {
return UnitBase<Unit_T>::FromValue(std::round(this->ToValue() * scalar)); return UnitBase<Unit_T>::FromValue(std::round(this->ToValue() * scalar));
} }
Unit_T operator*(const int64_t scalar) const { constexpr Unit_T operator*(int64_t scalar) const {
return UnitBase<Unit_T>::FromValue(this->ToValue() * scalar); return UnitBase<Unit_T>::FromValue(this->ToValue() * scalar);
} }
Unit_T operator*(const int32_t scalar) const { constexpr Unit_T operator*(int32_t scalar) const {
return UnitBase<Unit_T>::FromValue(this->ToValue() * scalar); return UnitBase<Unit_T>::FromValue(this->ToValue() * scalar);
} }
@ -286,17 +287,15 @@ class RelativeUnit : public UnitBase<Unit_T> {
}; };
template <class Unit_T> template <class Unit_T>
inline Unit_T operator*(const double scalar, const RelativeUnit<Unit_T> other) { inline constexpr Unit_T operator*(double scalar, RelativeUnit<Unit_T> other) {
return other * scalar; return other * scalar;
} }
template <class Unit_T> template <class Unit_T>
inline Unit_T operator*(const int64_t scalar, inline constexpr Unit_T operator*(int64_t scalar, RelativeUnit<Unit_T> other) {
const RelativeUnit<Unit_T> other) {
return other * scalar; return other * scalar;
} }
template <class Unit_T> template <class Unit_T>
inline Unit_T operator*(const int32_t& scalar, inline constexpr Unit_T operator*(int32_t scalar, RelativeUnit<Unit_T> other) {
const RelativeUnit<Unit_T> other) {
return other * scalar; return other * scalar;
} }

View File

@ -43,6 +43,10 @@ class TestUnit final : public rtc_units_impl::RelativeUnit<TestUnit> {
static constexpr bool one_sided = false; static constexpr bool one_sided = false;
using RelativeUnit<TestUnit>::RelativeUnit; using RelativeUnit<TestUnit>::RelativeUnit;
}; };
constexpr TestUnit TestUnitAddKilo(TestUnit value, int add_kilo) {
value += TestUnit::FromKilo(add_kilo);
return value;
}
} // namespace } // namespace
namespace test { namespace test {
TEST(UnitBaseTest, ConstExpr) { TEST(UnitBaseTest, ConstExpr) {
@ -62,6 +66,8 @@ TEST(UnitBaseTest, ConstExpr) {
static_assert(kTestUnitKilo.ToKiloOr(0) == kValue, ""); static_assert(kTestUnitKilo.ToKiloOr(0) == kValue, "");
static_assert(kTestUnitValue.ToValueOr(0) == kValue, ""); static_assert(kTestUnitValue.ToValueOr(0) == kValue, "");
static_assert(TestUnitAddKilo(kTestUnitValue, 2).ToValue() == kValue + 2000,
"");
} }
TEST(UnitBaseTest, GetBackSameValues) { TEST(UnitBaseTest, GetBackSameValues) {

View File

@ -30,7 +30,6 @@ ABSL_FLAG(std::string,
namespace webrtc { namespace webrtc {
namespace test { namespace test {
namespace { namespace {
const Timestamp kSimulatedStartTime = Timestamp::seconds(100000);
std::unique_ptr<FileLogWriterFactory> GetScenarioLogManager( std::unique_ptr<FileLogWriterFactory> GetScenarioLogManager(
std::string file_name) { std::string file_name) {