refactor: cast_ratio now uses quantity_ratio

This commit is contained in:
Mateusz Pusz
2020-09-07 11:11:12 +02:00
parent f3d9828abd
commit 00cb2cd6c3
2 changed files with 25 additions and 10 deletions

View File

@@ -44,10 +44,10 @@ concept safe_convertible = // exposition only
std::convertible_to<From, To> && std::convertible_to<From, To> &&
(treat_as_floating_point<To> || (!treat_as_floating_point<From>)); (treat_as_floating_point<To> || (!treat_as_floating_point<From>));
template<typename Rep, typename UnitFrom, typename UnitTo> template<typename Rep, typename QuantityFrom, typename QuantityTo>
concept safe_divisible = // exposition only concept safe_divisible = // exposition only
treat_as_floating_point<Rep> || treat_as_floating_point<Rep> ||
is_integral(UnitFrom::ratio / UnitTo::ratio); is_integral(quantity_ratio(QuantityFrom{}) / quantity_ratio(QuantityTo{}));
} // namespace detail } // namespace detail
@@ -81,7 +81,7 @@ public:
template<Quantity Q2> template<Quantity Q2>
requires equivalent_dim<D, typename Q2::dimension> && requires equivalent_dim<D, typename Q2::dimension> &&
detail::safe_convertible<typename Q2::rep, rep> && detail::safe_convertible<typename Q2::rep, rep> &&
detail::safe_divisible<rep, typename Q2::unit, unit> detail::safe_divisible<rep, Q2, quantity>
constexpr quantity(const Q2& q) : value_{quantity_cast<quantity>(q).count()} {} constexpr quantity(const Q2& q) : value_{quantity_cast<quantity>(q).count()} {}
quantity& operator=(const quantity&) = default; quantity& operator=(const quantity&) = default;

View File

@@ -38,6 +38,21 @@
namespace units { namespace units {
namespace detail {
template<typename D, typename U, typename Rep>
constexpr auto quantity_ratio(const quantity<D, U, Rep>&)
{
if constexpr(BaseDimension<D>) {
return U::ratio;
}
else {
return D::base_units_ratio * U::ratio / D::coherent_unit::ratio;
}
}
} // namespace detail
// QuantityOf // QuantityOf
template<typename T, typename Dim> template<typename T, typename Dim>
concept QuantityOf = Quantity<T> && Dimension<Dim> && equivalent_dim<typename T::dimension, Dim>; concept QuantityOf = Quantity<T> && Dimension<Dim> && equivalent_dim<typename T::dimension, Dim>;
@@ -266,16 +281,16 @@ struct quantity_cast_impl<To, CRatio, CRep, false, true, false> {
} }
}; };
template<Dimension FromD, Unit FromU, Dimension ToD, Unit ToU> template<typename Q1, typename Q2>
constexpr ratio cast_ratio() constexpr ratio cast_ratio(const Q1& from, const Q2& to)
{ {
if constexpr(BaseDimension<FromD> || same_unit_reference<FromU, ToU>::value) { using FromU = Q1::unit;
using ToU = Q2::unit;
if constexpr(same_unit_reference<FromU, ToU>::value) {
return FromU::ratio / ToU::ratio; return FromU::ratio / ToU::ratio;
} }
else { else {
const ratio from_ratio = FromD::base_units_ratio * FromU::ratio; return quantity_ratio(from) / quantity_ratio(to);
const ratio to_ratio = ToD::base_units_ratio * ToU::ratio;
return from_ratio / to_ratio;
} }
} }
@@ -297,7 +312,7 @@ template<Quantity To, typename D, typename U, typename Rep>
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q) [[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
requires QuantityOf<To, D> requires QuantityOf<To, D>
{ {
using c_ratio = std::integral_constant<ratio, detail::cast_ratio<D, U, typename To::dimension, typename To::unit>()>; using c_ratio = std::integral_constant<ratio, detail::cast_ratio(quantity<D, U, Rep>(), To())>;
using c_rep = std::common_type_t<typename To::rep, Rep>; using c_rep = std::common_type_t<typename To::rep, Rep>;
using ret_unit = downcast_unit<typename To::dimension, To::unit::ratio>; using ret_unit = downcast_unit<typename To::dimension, To::unit::ratio>;
using ret = quantity<typename To::dimension, ret_unit, typename To::rep>; using ret = quantity<typename To::dimension, ret_unit, typename To::rep>;