forked from mpusz/mp-units
refactor: quantity_spec casts functions renamed
This commit is contained in:
@@ -56,7 +56,7 @@ class quantity;
|
||||
* @tparam ToQS a quantity specification to use for a target quantity
|
||||
*/
|
||||
template<QuantitySpec auto ToQS, typename Q>
|
||||
requires Quantity<std::remove_cvref_t<Q>> && (castable_to(std::remove_cvref_t<Q>::quantity_spec, ToQS))
|
||||
requires Quantity<std::remove_cvref_t<Q>> && (castable(std::remove_cvref_t<Q>::quantity_spec, ToQS))
|
||||
[[nodiscard]] constexpr Quantity auto quantity_cast(Q&& q)
|
||||
{
|
||||
constexpr reference<ToQS, std::remove_cvref_t<Q>::unit> r;
|
||||
|
||||
@@ -56,7 +56,7 @@ concept Quantity = requires(T* t) { detail::to_base_specialization_of_quantity(t
|
||||
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)>> && implicitly_convertible_to(Q::quantity_spec, V)));
|
||||
(QuantitySpec<std::remove_const_t<decltype(V)>> && implicitly_convertible(Q::quantity_spec, V)));
|
||||
|
||||
/**
|
||||
* @brief A concept matching all external quantities like types
|
||||
|
||||
@@ -68,7 +68,7 @@ concept PointOrigin = QuantityPoint<T> || detail::is_derived_from_specialization
|
||||
* Satisfied by all quantity point origins that are defined using a provided quantity specification.
|
||||
*/
|
||||
template<typename T, auto Q>
|
||||
concept PointOriginFor = PointOrigin<T> && QuantitySpec<std::remove_const_t<decltype(Q)>> && Q == T::quantity_spec;
|
||||
concept PointOriginFor = PointOrigin<T> && QuantitySpec<std::remove_const_t<decltype(Q)>> && implicitly_convertible(Q, T::quantity_spec);
|
||||
|
||||
template<Reference auto R, PointOriginFor<get_quantity_spec(R)> auto PO,
|
||||
RepresentationOf<get_quantity_spec(R).character> Rep>
|
||||
@@ -95,7 +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)>> && implicitly_convertible_to(QP::quantity_spec, V)) ||
|
||||
(QuantitySpec<std::remove_const_t<decltype(V)>> && implicitly_convertible(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)>>));
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace detail {
|
||||
* @tparam To a target quantity type to cast to
|
||||
*/
|
||||
template<Quantity To, auto R, typename Rep>
|
||||
requires(castable_to(get_quantity_spec(R), To::quantity_spec)) &&
|
||||
requires(castable(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?
|
||||
|
||||
@@ -58,7 +58,7 @@ concept Harmonic = // exposition only
|
||||
|
||||
template<typename QFrom, typename QTo>
|
||||
concept QuantityConvertibleTo = // exposition only
|
||||
Quantity<QFrom> && Quantity<QTo> && implicitly_convertible_to(QFrom::quantity_spec, QTo::quantity_spec) &&
|
||||
Quantity<QFrom> && Quantity<QTo> && implicitly_convertible(QFrom::quantity_spec, QTo::quantity_spec) &&
|
||||
convertible_to(QFrom::unit, QTo::unit) && requires(QFrom q) { detail::sudo_cast<QTo>(q); } &&
|
||||
(treat_as_floating_point<typename QTo::rep> ||
|
||||
(!treat_as_floating_point<typename QFrom::rep> && Harmonic<QFrom::unit, QTo::unit>));
|
||||
|
||||
@@ -323,12 +323,12 @@ struct quantity_spec<Self, QS, Args...> : std::remove_const_t<decltype(QS)> {
|
||||
#ifdef __cpp_explicit_this_parameter
|
||||
template<detail::NamedQuantitySpec auto QS, detail::IntermediateDerivedQuantitySpec auto Eq,
|
||||
one_of<quantity_character> auto... Args>
|
||||
requires requires { QS._equation_; } && (implicitly_convertible_to(Eq, QS._equation_))
|
||||
requires requires { QS._equation_; } && (implicitly_convertible(Eq, QS._equation_))
|
||||
struct quantity_spec<QS, Eq, Args...> : quantity_spec<QS, Args...> {
|
||||
#else
|
||||
template<typename Self, detail::NamedQuantitySpec auto QS, detail::IntermediateDerivedQuantitySpec auto Eq,
|
||||
auto... Args>
|
||||
requires requires { QS._equation_; } && (implicitly_convertible_to(Eq, QS._equation_))
|
||||
requires requires { QS._equation_; } && (implicitly_convertible(Eq, QS._equation_))
|
||||
struct quantity_spec<Self, QS, Eq, Args...> : quantity_spec<Self, QS, Args...> {
|
||||
#endif
|
||||
static constexpr auto _equation_ = Eq;
|
||||
@@ -684,7 +684,7 @@ template<ratio Complexity, IntermediateDerivedQuantitySpec Q>
|
||||
}
|
||||
|
||||
template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
[[nodiscard]] consteval convertible_to_result convertible_to_impl(Q1 q1, Q2 q2)
|
||||
[[nodiscard]] consteval convertible_to_result convertible_impl(Q1 q1, Q2 q2)
|
||||
{
|
||||
using enum convertible_to_result;
|
||||
|
||||
@@ -695,9 +695,9 @@ template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
else if constexpr (QuantityKindSpec<Q1> || QuantityKindSpec<Q2>) {
|
||||
if constexpr (IntermediateDerivedQuantitySpec<Q1> &&
|
||||
NamedQuantitySpec<std::remove_const_t<decltype(remove_kind(q2))>>)
|
||||
return convertible_to_impl(get_kind(q1), remove_kind(q2));
|
||||
return convertible_impl(get_kind(q1), remove_kind(q2));
|
||||
else
|
||||
return convertible_to_impl(get_kind(q1), get_kind(q2)) != no ? yes : no;
|
||||
return convertible_impl(get_kind(q1), get_kind(q2)) != no ? yes : no;
|
||||
} else if constexpr (IntermediateDerivedQuantitySpec<Q1> && IntermediateDerivedQuantitySpec<Q2>)
|
||||
return are_ingredients_convertible_to(q1, q2);
|
||||
else if constexpr (NamedQuantitySpec<Q1> && NamedQuantitySpec<Q2>) {
|
||||
@@ -710,15 +710,15 @@ template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
} else if constexpr (IntermediateDerivedQuantitySpec<Q1>) {
|
||||
auto q1_exploded = explode<get_complexity(q2)>(q1);
|
||||
if constexpr (NamedQuantitySpec<std::remove_const_t<decltype(q1_exploded)>>)
|
||||
return convertible_to_impl(q1_exploded, q2);
|
||||
return convertible_impl(q1_exploded, q2);
|
||||
else if constexpr (requires { q2._equation_; })
|
||||
return convertible_to_impl(q1_exploded, q2._equation_);
|
||||
return convertible_impl(q1_exploded, q2._equation_);
|
||||
} else if constexpr (IntermediateDerivedQuantitySpec<Q2>) {
|
||||
auto q2_exploded = explode<get_complexity(q1)>(q2);
|
||||
if constexpr (NamedQuantitySpec<std::remove_const_t<decltype(q2_exploded)>>)
|
||||
return convertible_to_impl(q2_exploded, q1);
|
||||
return convertible_impl(q1, q2_exploded);
|
||||
else if constexpr (requires { q1._equation_; })
|
||||
return std::min(explicit_conversion, convertible_to_impl(q1._equation_, q2_exploded));
|
||||
return std::min(explicit_conversion, convertible_impl(q1._equation_, q2_exploded));
|
||||
}
|
||||
return no;
|
||||
}
|
||||
@@ -726,21 +726,21 @@ template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
} // namespace detail
|
||||
|
||||
template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
[[nodiscard]] consteval bool implicitly_convertible_to(Q1 q1, Q2 q2)
|
||||
[[nodiscard]] consteval bool implicitly_convertible(Q1 q1, Q2 q2)
|
||||
{
|
||||
return detail::convertible_to_impl(q1, q2) == detail::convertible_to_result::yes;
|
||||
return detail::convertible_impl(q1, q2) == detail::convertible_to_result::yes;
|
||||
}
|
||||
|
||||
template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
[[nodiscard]] consteval bool explicitly_convertible_to(Q1 q1, Q2 q2)
|
||||
[[nodiscard]] consteval bool explicitly_convertible(Q1 q1, Q2 q2)
|
||||
{
|
||||
return detail::convertible_to_impl(q1, q2) >= detail::convertible_to_result::explicit_conversion;
|
||||
return detail::convertible_impl(q1, q2) >= detail::convertible_to_result::explicit_conversion;
|
||||
}
|
||||
|
||||
template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
[[nodiscard]] consteval bool castable_to(Q1 q1, Q2 q2)
|
||||
[[nodiscard]] consteval bool castable(Q1 q1, Q2 q2)
|
||||
{
|
||||
return detail::convertible_to_impl(q1, q2) >= detail::convertible_to_result::cast;
|
||||
return detail::convertible_impl(q1, q2) >= detail::convertible_to_result::cast;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
@@ -783,14 +783,13 @@ template<QuantitySpec Q>
|
||||
|
||||
template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
[[nodiscard]] consteval QuantitySpec auto common_quantity_spec(Q1 q1, Q2 q2)
|
||||
requires(implicitly_convertible_to(get_kind(q1), get_kind(q2)) ||
|
||||
implicitly_convertible_to(get_kind(q2), get_kind(q1)))
|
||||
requires(implicitly_convertible(get_kind(q1), get_kind(q2)) || implicitly_convertible(get_kind(q2), get_kind(q1)))
|
||||
{
|
||||
if constexpr (q1 == q2)
|
||||
return q1;
|
||||
else if constexpr (detail::have_common_base(q1, q2))
|
||||
return detail::get_common_base(q1, q2);
|
||||
else if constexpr (implicitly_convertible_to(get_kind(q1), get_kind(q2)))
|
||||
else if constexpr (implicitly_convertible(get_kind(q1), get_kind(q2)))
|
||||
return get_kind(q2);
|
||||
else
|
||||
return get_kind(q1);
|
||||
|
||||
@@ -122,19 +122,19 @@ struct reference {
|
||||
template<auto Q2, auto U2>
|
||||
[[nodiscard]] friend consteval bool convertible_to(reference, reference<Q2, U2>)
|
||||
{
|
||||
return implicitly_convertible_to(Q, Q2) && convertible_to(U, U2);
|
||||
return implicitly_convertible(Q, Q2) && convertible_to(U, U2);
|
||||
}
|
||||
|
||||
template<AssociatedUnit U2>
|
||||
[[nodiscard]] friend consteval bool convertible_to(reference, U2 u2)
|
||||
{
|
||||
return implicitly_convertible_to(Q, get_quantity_spec(u2)) && convertible_to(U, u2);
|
||||
return implicitly_convertible(Q, get_quantity_spec(u2)) && convertible_to(U, u2);
|
||||
}
|
||||
|
||||
template<AssociatedUnit U1>
|
||||
[[nodiscard]] friend consteval bool convertible_to(U1 u1, reference)
|
||||
{
|
||||
return implicitly_convertible_to(get_quantity_spec(u1), Q) && convertible_to(u1, U);
|
||||
return implicitly_convertible(get_quantity_spec(u1), Q) && convertible_to(u1, U);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user