diff --git a/src/core/include/mp_units/bits/get_associated_quantity.h b/src/core/include/mp_units/bits/get_associated_quantity.h index e45f9144..81e93b7f 100644 --- a/src/core/include/mp_units/bits/get_associated_quantity.h +++ b/src/core/include/mp_units/bits/get_associated_quantity.h @@ -28,27 +28,59 @@ namespace mp_units::detail { +template +[[nodiscard]] consteval auto all_are_kinds(U); + template -[[nodiscard]] consteval auto get_associated_quantity(power) +[[nodiscard]] consteval auto all_are_kinds(power) { - return pow(get_associated_quantity(U{})); + return all_are_kinds(U{}); } -template -[[nodiscard]] consteval auto get_associated_quantity(type_list) +template +[[nodiscard]] consteval bool all_are_kinds(type_list, type_list) { - return (dimensionless * ... * get_associated_quantity(Us{})); + return (... && all_are_kinds(Nums{})) && (... && all_are_kinds(Dens{})); } template -[[nodiscard]] consteval auto get_associated_quantity(U) +[[nodiscard]] consteval auto all_are_kinds(U) { - if constexpr (requires { U::reference_unit; }) - return get_associated_quantity(U::reference_unit); - else if constexpr (requires { typename U::_num_; }) - return get_associated_quantity(typename U::_num_{}) / get_associated_quantity(typename U::_den_{}); - else if constexpr (requires { U::quantity_spec; }) - return U::quantity_spec; + if constexpr (requires { U::quantity_spec; }) + return QuantityKindSpec>; + else if constexpr (requires { U::reference_unit; }) + return all_are_kinds(U::reference_unit); + else if constexpr (requires { typename U::_num_; }) { + return all_are_kinds(typename U::_num_{}, typename U::_den_{}); + } +} + +template +[[nodiscard]] consteval auto get_associated_quantity_impl(U u); + +template +using to_quantity_spec = std::remove_const_t; + +template +[[nodiscard]] consteval auto get_associated_quantity_impl(U u) +{ + if constexpr (requires { U::quantity_spec; }) + return remove_kind(U::quantity_spec); + else if constexpr (requires { U::reference_unit; }) + return get_associated_quantity_impl(U::reference_unit); + else if constexpr (requires { typename U::_num_; }) { + return expr_map(u); + } +} + +template +[[nodiscard]] consteval auto get_associated_quantity(U u) +{ + constexpr bool all_kinds = all_are_kinds(u); + if constexpr (all_kinds) + return kind_of; + else + return get_associated_quantity_impl(u); } } // namespace mp_units::detail