feat: leveled quantity specification conversion introduced

This commit is contained in:
Mateusz Pusz
2023-02-10 17:16:51 -08:00
parent 761919c1be
commit a56696ee74
5 changed files with 10 additions and 23 deletions

View File

@@ -55,11 +55,11 @@ class quantity;
*
* @tparam ToQS a quantity specification to use for a target quantity
*/
template<QuantitySpec auto ToQS, Quantity Q>
requires(interconvertible(ToQS, get_quantity_spec(Q::reference)))
template<QuantitySpec auto ToQS, typename Q>
requires Quantity<std::remove_cvref_t<Q>> && castable_to(get_quantity_spec(Q::reference), ToQS)
[[nodiscard]] constexpr Quantity auto quantity_cast(Q&& q)
{
constexpr reference<ToQS, Q::unit> r;
constexpr reference<ToQS, std::remove_cvref_t<Q>::unit> r;
return std::forward<Q>(q).number() * r;
}

View File

@@ -54,21 +54,9 @@ concept Quantity = requires(T* t) { detail::to_base_specialization_of_quantity(t
* the provided dimension/reference type.
*/
template<typename Q, auto V>
concept QuantityOf = Quantity<Q> && ((Dimension<std::remove_const_t<decltype(V)>> && Q::dimension == V) ||
(QuantitySpec<std::remove_const_t<decltype(V)>> && Q::quantity_spec == V) ||
(Reference<std::remove_const_t<decltype(V)>> && Q::reference == V));
/**
* @brief A concept matching all quantities with provided dimension or reference
*
* Satisfied by all quantities with a dimension/reference being the instantiation derived from
* the provided dimension/reference type.
*/
template<typename Q, auto V>
concept WeakQuantityOf =
concept QuantityOf =
Quantity<Q> && ((Dimension<std::remove_const_t<decltype(V)>> && Q::dimension == V) ||
(QuantitySpec<std::remove_const_t<decltype(V)>> && interconvertible(Q::quantity_spec, V)) ||
(Reference<std::remove_const_t<decltype(V)>> && Q::dimension == V.dimension && Q::unit == V.unit));
(QuantitySpec<std::remove_const_t<decltype(V)>> && implicitly_convertible_to(Q::quantity_spec, V)));
/**
* @brief A concept matching all external quantities like types

View File

@@ -95,8 +95,7 @@ template<typename QP, auto V>
concept QuantityPointOf =
QuantityPoint<QP> &&
((Dimension<std::remove_const_t<decltype(V)>> && QP::dimension == V) ||
(QuantitySpec<std::remove_const_t<decltype(V)>> && QP::quantity_spec == V) ||
(Reference<std::remove_const_t<decltype(V)>> && QP::reference == V) ||
(QuantitySpec<std::remove_const_t<decltype(V)>> && implicitly_convertible_to(QP::quantity_spec, V)) ||
(PointOrigin<std::remove_const_t<decltype(V)>> &&
std::same_as<std::remove_const_t<decltype(QP::absolute_point_origin)>, std::remove_const_t<decltype(V)>>));

View File

@@ -43,7 +43,7 @@ namespace detail {
* @tparam To a target quantity type to cast to
*/
template<Quantity To, auto R, typename Rep>
requires(interconvertible(To::reference, R)) &&
requires(castable_to(get_quantity_spec(R), To::quantity_spec)) &&
((get_unit(R) == To::unit && std::constructible_from<typename To::rep, Rep>) ||
(get_unit(R) != To::unit)) // && scalable_with_<typename To::rep>))
// TODO how to constrain the second part here?

View File

@@ -122,19 +122,19 @@ struct reference {
template<auto Q2, auto U2>
[[nodiscard]] friend consteval bool convertible_to(reference, reference<Q2, U2>)
{
return convertible_to(Q, Q2) && convertible_to(U, U2);
return implicitly_convertible_to(Q, Q2) && convertible_to(U, U2);
}
template<AssociatedUnit U2>
[[nodiscard]] friend consteval bool convertible_to(reference, U2 u2)
{
return convertible_to(Q, get_quantity_spec(u2)) && convertible_to(U, u2);
return implicitly_convertible_to(Q, get_quantity_spec(u2)) && convertible_to(U, u2);
}
template<AssociatedUnit U1>
[[nodiscard]] friend consteval bool convertible_to(U1 u1, reference)
{
return convertible_to(get_quantity_spec(u1), Q) && convertible_to(u1, U);
return implicitly_convertible_to(get_quantity_spec(u1), Q) && convertible_to(u1, U);
}
};