fix: constraits for magnitude added for scaled_unit and fixed common_unit instantiating it incorrectly

This commit is contained in:
Mateusz Pusz
2024-10-01 21:36:33 +02:00
parent 4a98817c15
commit 246defb9b2
2 changed files with 19 additions and 1 deletions

View File

@@ -59,6 +59,9 @@ import std;
namespace mp_units { namespace mp_units {
template<Unit U1, Unit U2, Unit... Rest>
struct common_unit;
namespace detail { namespace detail {
template<Magnitude auto M, Unit U> template<Magnitude auto M, Unit U>
@@ -112,6 +115,9 @@ template<Unit T, typename... Expr>
template<Unit T, auto M, typename U> template<Unit T, auto M, typename U>
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const scaled_unit_impl<M, U>&); [[nodiscard]] consteval auto get_canonical_unit_impl(T, const scaled_unit_impl<M, U>&);
template<Unit T, typename... Us>
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const common_unit<Us...>&);
template<Unit Lhs, Unit Rhs> template<Unit Lhs, Unit Rhs>
struct unit_less : std::bool_constant<type_name<Lhs>() < type_name<Rhs>()> {}; struct unit_less : std::bool_constant<type_name<Lhs>() < type_name<Rhs>()> {};
@@ -237,6 +243,7 @@ struct scaled_unit_impl : detail::unit_interface, detail::propagate_point_origin
* instantiate this type automatically based on the unit arithmetic equation provided by the user. * instantiate this type automatically based on the unit arithmetic equation provided by the user.
*/ */
template<Magnitude auto M, Unit U> template<Magnitude auto M, Unit U>
requires(M != magnitude<>{} && M != mag<1>)
struct scaled_unit final : detail::scaled_unit_impl<M, U> {}; struct scaled_unit final : detail::scaled_unit_impl<M, U> {};
namespace detail { namespace detail {
@@ -412,7 +419,10 @@ template<Unit U1, Unit U2>
constexpr auto canonical_lhs = get_canonical_unit(U1{}); constexpr auto canonical_lhs = get_canonical_unit(U1{});
constexpr auto canonical_rhs = get_canonical_unit(U2{}); constexpr auto canonical_rhs = get_canonical_unit(U2{});
constexpr auto common_magnitude = _common_magnitude(canonical_lhs.mag, canonical_rhs.mag); constexpr auto common_magnitude = _common_magnitude(canonical_lhs.mag, canonical_rhs.mag);
return scaled_unit<common_magnitude, decltype(canonical_lhs.reference_unit)>{}; if constexpr (common_magnitude == mag<1>)
return canonical_lhs.reference_unit;
else
return scaled_unit<common_magnitude, std::remove_const_t<decltype(canonical_lhs.reference_unit)>>{};
} }
[[nodiscard]] consteval Unit auto get_common_scaled_unit(Unit auto u1, Unit auto u2, Unit auto u3, Unit auto... rest) [[nodiscard]] consteval Unit auto get_common_scaled_unit(Unit auto u1, Unit auto u2, Unit auto u3, Unit auto... rest)
@@ -441,6 +451,7 @@ template<Unit U1, Unit U2, Unit... Rest>
struct common_unit final : decltype(detail::get_common_scaled_unit(U1{}, U2{}, Rest{}...))::_base_type_ struct common_unit final : decltype(detail::get_common_scaled_unit(U1{}, U2{}, Rest{}...))::_base_type_
{ {
using _base_type_ = common_unit; // exposition only using _base_type_ = common_unit; // exposition only
static constexpr auto _common_unit_ = detail::get_common_scaled_unit(U1{}, U2{}, Rest{}...);
}; };
namespace detail { namespace detail {
@@ -524,6 +535,12 @@ template<Unit T, auto M, typename U>
return canonical_unit{M * base.mag, base.reference_unit}; return canonical_unit{M * base.mag, base.reference_unit};
} }
template<Unit T, typename... Us>
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const common_unit<Us...>& u)
{
return get_canonical_unit_impl(u._common_unit_, u._common_unit_);
}
template<Unit T, symbol_text Symbol, auto... Args> template<Unit T, symbol_text Symbol, auto... Args>
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Args...>&) [[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Args...>&)
{ {

View File

@@ -46,6 +46,7 @@ MP_UNITS_EXPORT template<typename T>
concept Unit = std::derived_from<T, detail::unit_interface> && std::is_final_v<T>; concept Unit = std::derived_from<T, detail::unit_interface> && std::is_final_v<T>;
template<Magnitude auto M, Unit U> template<Magnitude auto M, Unit U>
requires(M != magnitude<>{} && M != mag<1>)
struct scaled_unit; struct scaled_unit;
MP_UNITS_EXPORT template<symbol_text Symbol, auto...> MP_UNITS_EXPORT template<symbol_text Symbol, auto...>