fix: common_unit handling fixed for some corner cases

This commit is contained in:
Mateusz Pusz committed 2024-10-05 17:52:52 +02:00
1 parent 07e4e795c1
commit 569f27af8b
7 files changed
+58 -12

No files matched your search

@@ -26,7 +26,12 @@
#include <mp-units/framework/quantity_spec.h>
#include <mp-units/framework/unit_concepts.h>
namespace mp_units::detail {
namespace mp_units {
template<Unit U1, Unit U2, Unit... Rest>
struct common_unit;
namespace detail {
template<AssociatedUnit U>
[[nodiscard]] consteval auto all_are_kinds(U);
@@ -61,6 +66,12 @@ template<AssociatedUnit U>
template<AssociatedUnit U>
using to_quantity_spec = decltype(get_associated_quantity_impl(U{}));
template<typename... Us>
[[nodiscard]] consteval auto get_associated_quantity_impl(common_unit<Us...>)
{
return get_common_quantity_spec(get_associated_quantity_impl(Us{})...);
}
template<AssociatedUnit U>
[[nodiscard]] consteval auto get_associated_quantity_impl(U u)
{
@@ -83,4 +94,6 @@ template<AssociatedUnit U>
return get_associated_quantity_impl(u);
}
} // namespace mp_units::detail
} // namespace detail
} // namespace mp_units
@@ -93,16 +93,17 @@ concept HaveCommonReferenceImpl = requires { get_common_reference(R1, R2); };
template<auto R1, auto R2>
concept HaveCommonReference = HaveCommonReferenceImpl<R1, R2>;
template<typename Func, Quantity Q1, Quantity Q2>
using common_quantity_for = quantity<get_common_reference(Q1::reference, Q2::reference),
std::invoke_result_t<Func, typename Q1::rep, typename Q2::rep>>;
template<typename Func, typename Q1, typename Q2>
concept CommonlyInvocableQuantities =
Quantity<Q1> && Quantity<Q2> && HaveCommonReference<Q1::reference, Q2::reference> &&
std::convertible_to<Q1, common_quantity_for<Func, Q1, Q2>> &&
std::convertible_to<Q2, common_quantity_for<Func, Q1, Q2>> &&
InvocableQuantities<Func, Q1, Q2, get_common_quantity_spec(Q1::quantity_spec, Q2::quantity_spec).character>;
template<typename Func, Quantity Q1, Quantity Q2>
requires CommonlyInvocableQuantities<Func, Q1, Q2>
using common_quantity_for = quantity<get_common_reference(Q1::reference, Q2::reference),
std::invoke_result_t<Func, typename Q1::rep, typename Q2::rep>>;
template<auto R1, auto R2, typename Rep1, typename Rep2>
concept SameValueAs = SameReference<R1, R2> && std::same_as<Rep1, Rep2>;
+11 -5
View File
@@ -60,9 +60,6 @@ import std;
namespace mp_units {
template<Unit U1, Unit U2, Unit... Rest>
struct common_unit;
namespace detail {
template<Magnitude auto M, Unit U>
@@ -784,9 +781,18 @@ constexpr Out unit_symbol_impl(Out out, const scaled_unit_impl<M, U>& u, const u
template<typename... Us, Unit U>
[[nodiscard]] consteval Unit auto get_common_unit_in(common_unit<Us...>, U u)
{
auto get_magnitude = [&]() {
if constexpr (requires { common_unit<Us...>::mag; })
return common_unit<Us...>::mag;
else
return mag<1>;
};
constexpr auto canonical_u = get_canonical_unit(u);
constexpr Magnitude auto mag = common_unit<Us...>::mag / canonical_u.mag;
return scaled_unit<mag, U>{};
constexpr Magnitude auto cmag = get_magnitude() / canonical_u.mag;
if constexpr (cmag == mag<1>)
return u;
else
return scaled_unit<cmag, U>{};
}
template<typename CharT, std::output_iterator<CharT> Out, typename U, typename... Rest>