mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-06 13:44:27 +02:00
feat: leveled quantity specification conversion introduced
This commit is contained in:
@@ -55,11 +55,11 @@ class quantity;
|
|||||||
*
|
*
|
||||||
* @tparam ToQS a quantity specification to use for a target quantity
|
* @tparam ToQS a quantity specification to use for a target quantity
|
||||||
*/
|
*/
|
||||||
template<QuantitySpec auto ToQS, Quantity Q>
|
template<QuantitySpec auto ToQS, typename Q>
|
||||||
requires(interconvertible(ToQS, get_quantity_spec(Q::reference)))
|
requires Quantity<std::remove_cvref_t<Q>> && castable_to(get_quantity_spec(Q::reference), ToQS)
|
||||||
[[nodiscard]] constexpr Quantity auto quantity_cast(Q&& q)
|
[[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;
|
return std::forward<Q>(q).number() * r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -54,21 +54,9 @@ concept Quantity = requires(T* t) { detail::to_base_specialization_of_quantity(t
|
|||||||
* the provided dimension/reference type.
|
* the provided dimension/reference type.
|
||||||
*/
|
*/
|
||||||
template<typename Q, auto V>
|
template<typename Q, auto V>
|
||||||
concept QuantityOf = Quantity<Q> && ((Dimension<std::remove_const_t<decltype(V)>> && Q::dimension == V) ||
|
concept QuantityOf =
|
||||||
(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 =
|
|
||||||
Quantity<Q> && ((Dimension<std::remove_const_t<decltype(V)>> && Q::dimension == V) ||
|
Quantity<Q> && ((Dimension<std::remove_const_t<decltype(V)>> && Q::dimension == V) ||
|
||||||
(QuantitySpec<std::remove_const_t<decltype(V)>> && interconvertible(Q::quantity_spec, V)) ||
|
(QuantitySpec<std::remove_const_t<decltype(V)>> && implicitly_convertible_to(Q::quantity_spec, V)));
|
||||||
(Reference<std::remove_const_t<decltype(V)>> && Q::dimension == V.dimension && Q::unit == V.unit));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A concept matching all external quantities like types
|
* @brief A concept matching all external quantities like types
|
||||||
|
@@ -95,8 +95,7 @@ template<typename QP, auto V>
|
|||||||
concept QuantityPointOf =
|
concept QuantityPointOf =
|
||||||
QuantityPoint<QP> &&
|
QuantityPoint<QP> &&
|
||||||
((Dimension<std::remove_const_t<decltype(V)>> && QP::dimension == V) ||
|
((Dimension<std::remove_const_t<decltype(V)>> && QP::dimension == V) ||
|
||||||
(QuantitySpec<std::remove_const_t<decltype(V)>> && QP::quantity_spec == V) ||
|
(QuantitySpec<std::remove_const_t<decltype(V)>> && implicitly_convertible_to(QP::quantity_spec, V)) ||
|
||||||
(Reference<std::remove_const_t<decltype(V)>> && QP::reference == V) ||
|
|
||||||
(PointOrigin<std::remove_const_t<decltype(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)>>));
|
std::same_as<std::remove_const_t<decltype(QP::absolute_point_origin)>, std::remove_const_t<decltype(V)>>));
|
||||||
|
|
||||||
|
@@ -43,7 +43,7 @@ namespace detail {
|
|||||||
* @tparam To a target quantity type to cast to
|
* @tparam To a target quantity type to cast to
|
||||||
*/
|
*/
|
||||||
template<Quantity To, auto R, typename Rep>
|
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 && std::constructible_from<typename To::rep, Rep>) ||
|
||||||
(get_unit(R) != To::unit)) // && scalable_with_<typename To::rep>))
|
(get_unit(R) != To::unit)) // && scalable_with_<typename To::rep>))
|
||||||
// TODO how to constrain the second part here?
|
// TODO how to constrain the second part here?
|
||||||
|
@@ -122,19 +122,19 @@ struct reference {
|
|||||||
template<auto Q2, auto U2>
|
template<auto Q2, auto U2>
|
||||||
[[nodiscard]] friend consteval bool convertible_to(reference, reference<Q2, 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>
|
template<AssociatedUnit U2>
|
||||||
[[nodiscard]] friend consteval bool convertible_to(reference, U2 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>
|
template<AssociatedUnit U1>
|
||||||
[[nodiscard]] friend consteval bool convertible_to(U1 u1, reference)
|
[[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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user