forked from mpusz/mp-units
feat: full-on dimensional analysis between related quantity kinds
This commit is contained in:
committed by
Mateusz Pusz
parent
dad9b4f166
commit
017183653d
@@ -246,6 +246,16 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Rep2>
|
||||
constexpr quantity& operator%=(const dimensionless<units::one, Rep2>& rhs)
|
||||
requires (!floating_point_<rep>) && (!floating_point_<Rep2>) &&
|
||||
requires(rep a, const Rep2 b) { { a %= b } -> std::same_as<rep&>; }
|
||||
{
|
||||
gsl_ExpectsAudit(rhs.count() != quantity_values<Rep2>::zero());
|
||||
value_ %= rhs.count();
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr quantity& operator%=(const quantity& q)
|
||||
requires (!floating_point_<rep>) &&
|
||||
requires(rep a, rep b) { { a %= b } -> std::same_as<rep&>; }
|
||||
|
||||
@@ -53,6 +53,15 @@ inline constexpr auto& downcasted_kind = downcasted_kind_fn<typename QK::kind_ty
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @brief A concept matching two related quantity kinds
|
||||
*
|
||||
* Satisfied by quantity kinds having equivalent base kinds.
|
||||
*/
|
||||
template<typename QK1, typename QK2>
|
||||
concept QuantityKindRelatedTo = QuantityKind<QK1> && QuantityKind<QK2> &&
|
||||
equivalent<typename QK1::kind_type::base_kind, typename QK2::kind_type::base_kind>;
|
||||
|
||||
/**
|
||||
* @brief A quantity kind
|
||||
*
|
||||
@@ -180,6 +189,13 @@ public:
|
||||
q_ *= rhs;
|
||||
return *this;
|
||||
}
|
||||
template<typename Rep2>
|
||||
constexpr quantity_kind& operator*=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs)
|
||||
requires requires(quantity_type q) { q *= rhs.common(); }
|
||||
{
|
||||
q_ *= rhs.common();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Rep2>
|
||||
constexpr quantity_kind& operator/=(const Rep2& rhs)
|
||||
@@ -189,15 +205,29 @@ public:
|
||||
q_ /= rhs;
|
||||
return *this;
|
||||
}
|
||||
template<typename Rep2>
|
||||
constexpr quantity_kind& operator/=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs)
|
||||
requires requires(quantity_type q) { q /= rhs.common(); }
|
||||
{
|
||||
q_ /= rhs.common();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Rep2>
|
||||
constexpr quantity_kind& operator%=(const Rep2& rhs)
|
||||
requires (!Quantity<Rep2>) && requires(quantity_type q, const Rep2 r) { q %= r; }
|
||||
requires (!Quantity<Rep2> || Dimensionless<Rep2>) && requires(quantity_type q, const Rep2 r) { q %= r; }
|
||||
{
|
||||
gsl_ExpectsAudit(rhs != quantity_values<Rep2>::zero());
|
||||
q_ %= rhs;
|
||||
return *this;
|
||||
}
|
||||
template<typename Rep2>
|
||||
constexpr quantity_kind& operator%=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs)
|
||||
requires requires(quantity_type q) { q %= rhs.common(); }
|
||||
{
|
||||
q_ %= rhs.common();
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr quantity_kind& operator%=(const quantity_kind& qk)
|
||||
requires requires(quantity_type q) { q %= qk.common(); }
|
||||
@@ -256,9 +286,6 @@ public:
|
||||
[[nodiscard]] friend constexpr bool operator==(const quantity_kind&, const quantity_kind&) = default;
|
||||
};
|
||||
|
||||
template<Kind K, QuantityValue V>
|
||||
explicit(false) quantity_kind(K, V) -> quantity_kind<K, one, V>;
|
||||
|
||||
template<QuantityKind QK1, QuantityKindEquivalentTo<QK1> QK2>
|
||||
[[nodiscard]] constexpr QuantityKind auto operator+(const QK1& lhs, const QK2& rhs)
|
||||
requires requires { lhs.common() + rhs.common(); }
|
||||
@@ -287,6 +314,13 @@ template<Quantity Q, QuantityKind QK>
|
||||
return detail::downcasted_kind<QK>(lhs * rhs.common());
|
||||
}
|
||||
|
||||
template<QuantityKind QK1, QuantityKindRelatedTo<QK1> QK2>
|
||||
[[nodiscard]] constexpr QuantityKind auto operator*(const QK1& lhs, const QK2& rhs)
|
||||
requires requires { lhs.common() * rhs.common(); }
|
||||
{
|
||||
return detail::downcasted_kind<QK1>(lhs.common() * rhs.common());
|
||||
}
|
||||
|
||||
template<QuantityKind QK, Quantity Q>
|
||||
[[nodiscard]] constexpr QuantityKind auto operator/(const QK& lhs, const Q& rhs)
|
||||
requires requires { lhs.common() / rhs; }
|
||||
@@ -303,6 +337,13 @@ template<Quantity Q, QuantityKind QK>
|
||||
return detail::downcasted_kind<QK>(lhs / rhs.common());
|
||||
}
|
||||
|
||||
template<QuantityKind QK1, QuantityKindRelatedTo<QK1> QK2>
|
||||
[[nodiscard]] constexpr QuantityKind auto operator/(const QK1& lhs, const QK2& rhs)
|
||||
requires requires { lhs.common() / rhs.common(); }
|
||||
{
|
||||
return detail::downcasted_kind<QK1>(lhs.common() / rhs.common());
|
||||
}
|
||||
|
||||
template<QuantityKind QK, Dimensionless D>
|
||||
[[nodiscard]] constexpr QuantityKind auto operator%(const QK& lhs, const D& rhs)
|
||||
requires requires { lhs.common() % rhs; }
|
||||
|
||||
@@ -182,9 +182,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
template<PointKind PK, QuantityValue V>
|
||||
explicit(false) quantity_point_kind(PK, V) -> quantity_point_kind<PK, one, V>;
|
||||
|
||||
template<QuantityKind QK>
|
||||
quantity_point_kind(QK) ->
|
||||
quantity_point_kind<downcast_point_kind<typename QK::kind_type>, typename QK::unit, typename QK::rep>;
|
||||
|
||||
Reference in New Issue
Block a user