diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index eb38df01..e9b5fa38 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -44,10 +44,10 @@ concept safe_convertible = // exposition only std::convertible_to && (treat_as_floating_point || (!treat_as_floating_point)); -template +template concept safe_divisible = // exposition only treat_as_floating_point || - is_integral(UnitFrom::ratio / UnitTo::ratio); + is_integral(quantity_ratio(QuantityFrom{}) / quantity_ratio(QuantityTo{})); } // namespace detail @@ -81,7 +81,7 @@ public: template requires equivalent_dim && detail::safe_convertible && - detail::safe_divisible + detail::safe_divisible constexpr quantity(const Q2& q) : value_{quantity_cast(q).count()} {} quantity& operator=(const quantity&) = default; diff --git a/src/include/units/quantity_cast.h b/src/include/units/quantity_cast.h index 362bd43e..f9e23f4d 100644 --- a/src/include/units/quantity_cast.h +++ b/src/include/units/quantity_cast.h @@ -38,6 +38,21 @@ namespace units { +namespace detail { + +template +constexpr auto quantity_ratio(const quantity&) +{ + if constexpr(BaseDimension) { + return U::ratio; + } + else { + return D::base_units_ratio * U::ratio / D::coherent_unit::ratio; + } +} + +} // namespace detail + // QuantityOf template concept QuantityOf = Quantity && Dimension && equivalent_dim; @@ -266,16 +281,16 @@ struct quantity_cast_impl { } }; -template -constexpr ratio cast_ratio() +template +constexpr ratio cast_ratio(const Q1& from, const Q2& to) { - if constexpr(BaseDimension || same_unit_reference::value) { + using FromU = Q1::unit; + using ToU = Q2::unit; + if constexpr(same_unit_reference::value) { return FromU::ratio / ToU::ratio; } else { - const ratio from_ratio = FromD::base_units_ratio * FromU::ratio; - const ratio to_ratio = ToD::base_units_ratio * ToU::ratio; - return from_ratio / to_ratio; + return quantity_ratio(from) / quantity_ratio(to); } } @@ -297,7 +312,7 @@ template [[nodiscard]] constexpr auto quantity_cast(const quantity& q) requires QuantityOf { - using c_ratio = std::integral_constant()>; + using c_ratio = std::integral_constant(), To())>; using c_rep = std::common_type_t; using ret_unit = downcast_unit; using ret = quantity;