feat: proper support of kinds added to get_associated_quantity()

This commit is contained in:
Mateusz Pusz
2023-02-13 18:13:41 +01:00
parent 9436229ed2
commit a13e627c9f

View File

@@ -28,27 +28,59 @@
namespace mp_units::detail {
template<AssociatedUnit U>
[[nodiscard]] consteval auto all_are_kinds(U);
template<typename U, auto... Vs>
[[nodiscard]] consteval auto get_associated_quantity(power<U, Vs...>)
[[nodiscard]] consteval auto all_are_kinds(power<U, Vs...>)
{
return pow<Vs...>(get_associated_quantity(U{}));
return all_are_kinds(U{});
}
template<typename... Us>
[[nodiscard]] consteval auto get_associated_quantity(type_list<Us...>)
template<typename... Nums, typename... Dens>
[[nodiscard]] consteval bool all_are_kinds(type_list<Nums...>, type_list<Dens...>)
{
return (dimensionless * ... * get_associated_quantity(Us{}));
return (... && all_are_kinds(Nums{})) && (... && all_are_kinds(Dens{}));
}
template<AssociatedUnit U>
[[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<std::remove_const_t<decltype(U::quantity_spec)>>;
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<AssociatedUnit U>
[[nodiscard]] consteval auto get_associated_quantity_impl(U u);
template<AssociatedUnit U>
using to_quantity_spec = std::remove_const_t<decltype(get_associated_quantity_impl(U{}))>;
template<AssociatedUnit U>
[[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<to_quantity_spec, derived_quantity_spec, struct dimensionless, type_list_of_quantity_spec_less>(u);
}
}
template<AssociatedUnit U>
[[nodiscard]] consteval auto get_associated_quantity(U u)
{
constexpr bool all_kinds = all_are_kinds(u);
if constexpr (all_kinds)
return kind_of<get_associated_quantity_impl(u)>;
else
return get_associated_quantity_impl(u);
}
} // namespace mp_units::detail