From d9b227ad30ebaa7b1e15af97cb77186504aa285b Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Sun, 4 Dec 2022 15:04:37 +0100 Subject: [PATCH] feat: units now allow inheritance For example to define `cgs::second` based on `si::second` --- src/core/include/units/unit.h | 50 ++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/core/include/units/unit.h b/src/core/include/units/unit.h index 209c9b0c..13fb9268 100644 --- a/src/core/include/units/unit.h +++ b/src/core/include/units/unit.h @@ -528,8 +528,7 @@ template return scaled_unit{}; } -template -[[nodiscard]] consteval Unit auto operator*(U, M) = delete; +[[nodiscard]] consteval Unit auto operator*(Unit auto, Magnitude auto) = delete; /** * `scaled_unit` specializations have priority in this operation. This means that the library framework @@ -567,22 +566,53 @@ template return detail::expr_divide(lhs, rhs); } -template -[[nodiscard]] consteval Unit auto operator/(int value, U u) +[[nodiscard]] consteval Unit auto operator/(int value, Unit auto u) { gsl_Expects(value == 1); return detail::expr_invert(u); } -template -[[nodiscard]] consteval Unit auto operator/(U, int) = delete; +[[nodiscard]] consteval Unit auto operator/(Unit auto, int) = delete; -template -[[nodiscard]] consteval bool operator==(Lhs lhs, Rhs rhs) +namespace detail { + +consteval bool same_canonical_reference_unit(...) { return false; } + +template +consteval bool same_canonical_reference_unit(const named_unit&, const named_unit&) +{ + return true; +} + +template +consteval bool same_canonical_reference_unit(const power&, const power&) +{ + return same_canonical_reference_unit(F1{}, F2{}); +} + +template + requires(sizeof...(Us1) == sizeof...(Us2)) +consteval bool same_canonical_reference_unit(const type_list&, const type_list&) +{ + return (... && same_canonical_reference_unit(Us1{}, Us2{})); +} + +template +consteval bool same_canonical_reference_unit(const derived_unit&, const derived_unit&) +{ + return same_canonical_reference_unit(typename derived_unit::_num_{}, + typename derived_unit::_num_{}) && + same_canonical_reference_unit(typename derived_unit::_den_{}, typename derived_unit::_den_{}); +} + +} // namespace detail + + +[[nodiscard]] consteval bool operator==(Unit auto lhs, Unit auto rhs) { auto canonical_lhs = detail::get_canonical_unit(lhs); auto canonical_rhs = detail::get_canonical_unit(rhs); - return is_same_v && + return detail::same_canonical_reference_unit(canonical_lhs.reference_unit, canonical_rhs.reference_unit) && canonical_lhs.mag == canonical_rhs.mag; } @@ -591,7 +621,7 @@ template { auto canonical_lhs = detail::get_canonical_unit(u1); auto canonical_rhs = detail::get_canonical_unit(u2); - return is_same_v; + return detail::same_canonical_reference_unit(canonical_lhs.reference_unit, canonical_rhs.reference_unit); } // Common unit