feat: full-on dimensional analysis between related quantity kinds

This commit is contained in:
Johel Ernesto Guerrero Peña
2021-02-21 00:17:03 +01:00
committed by Mateusz Pusz
parent dad9b4f166
commit 017183653d
11 changed files with 295 additions and 49 deletions
+10
View File
@@ -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&>; }
+45 -4
View File
@@ -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; }
-3
View File
@@ -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>;