diff --git a/src/core/include/mp-units/quantity.h b/src/core/include/mp-units/quantity.h index 88d6a43f..6c3f9f1b 100644 --- a/src/core/include/mp-units/quantity.h +++ b/src/core/include/mp-units/quantity.h @@ -269,88 +269,97 @@ public: } // compound assignment operators - constexpr quantity& operator+=(const quantity& q) - requires requires(rep a, rep b) { + template + requires std::derived_from, quantity> && requires(rep a, rep b) { { a += b } -> std::same_as; } + friend constexpr decltype(auto) operator+=(Q&& lhs, const quantity& rhs) { - numerical_value_ += q.numerical_value_ref_in(unit); - return *this; + lhs.numerical_value_ += rhs.numerical_value_; + return std::forward(lhs); } - constexpr quantity& operator-=(const quantity& q) - requires requires(rep a, rep b) { + template + requires std::derived_from, quantity> && requires(rep a, rep b) { { a -= b } -> std::same_as; } + friend constexpr decltype(auto) operator-=(Q&& lhs, const quantity& rhs) { - numerical_value_ -= q.numerical_value_ref_in(unit); - return *this; + lhs.numerical_value_ -= rhs.numerical_value_; + return std::forward(lhs); } - constexpr quantity& operator%=(const quantity& q) - requires(!treat_as_floating_point) && requires(rep a, rep b) { - { - a %= b - } -> std::same_as; - } + template + requires std::derived_from, quantity> && (!treat_as_floating_point) && + requires(rep a, rep b) { + { + a %= b + } -> std::same_as; + } + friend constexpr decltype(auto) operator%=(Q&& lhs, const quantity& rhs) + { - gsl_ExpectsAudit(q != zero()); - numerical_value_ %= q.numerical_value_ref_in(unit); - return *this; + gsl_ExpectsAudit(rhs != zero()); + lhs.numerical_value_ %= rhs.numerical_value_; + return std::forward(lhs); } - template - requires(!Quantity) && requires(rep a, const Value b) { - { - a *= b - } -> std::same_as; - } - constexpr quantity& operator*=(const Value& v) + template + requires std::derived_from, quantity> && (!Quantity) && + requires(rep a, const Value b) { + { + a *= b + } -> std::same_as; + } + friend constexpr decltype(auto) operator*=(Q&& lhs, const Value& v) { - numerical_value_ *= v; - return *this; + lhs.numerical_value_ *= v; + return std::forward(lhs); } - template Q> - requires(Q::unit == ::mp_units::one) && requires(rep a, const typename Q::rep b) { - { - a *= b - } -> std::same_as; - } - constexpr quantity& operator*=(const Q& rhs) + template Q2> + requires std::derived_from, quantity> && (Q2::unit == ::mp_units::one) && + requires(rep a, const typename Q2::rep b) { + { + a *= b + } -> std::same_as; + } + friend constexpr decltype(auto) operator*=(Q1&& lhs, const Q2& rhs) { - numerical_value_ *= rhs.numerical_value_ref_in(::mp_units::one); - return *this; + lhs.numerical_value_ *= rhs.numerical_value_; + return std::forward(lhs); } - template - requires(!Quantity) && requires(rep a, const Value b) { - { - a /= b - } -> std::same_as; - } - constexpr quantity& operator/=(const Value& v) + template + requires std::derived_from, quantity> && (!Quantity) && + requires(rep a, const Value b) { + { + a /= b + } -> std::same_as; + } + friend constexpr decltype(auto) operator/=(Q&& lhs, const Value& v) { gsl_ExpectsAudit(v != quantity_values::zero()); - numerical_value_ /= v; - return *this; + lhs.numerical_value_ /= v; + return std::forward(lhs); } - template Q> - requires(Q::unit == ::mp_units::one) && requires(rep a, const typename Q::rep b) { - { - a /= b - } -> std::same_as; - } - constexpr quantity& operator/=(const Q& rhs) + template Q2> + requires std::derived_from, quantity> && (Q2::unit == ::mp_units::one) && + requires(rep a, const typename Q2::rep b) { + { + a /= b + } -> std::same_as; + } + friend constexpr decltype(auto) operator/=(Q1&& lhs, const Q2& rhs) { gsl_ExpectsAudit(rhs != rhs.zero()); - numerical_value_ /= rhs.numerical_value_ref_in(::mp_units::one); - return *this; + lhs.numerical_value_ /= rhs.numerical_value_; + return std::forward(lhs); } private: