mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-30 02:17:16 +02:00
refactor: get_associated_quantity
and quantity spec hierarchy traversing compile-times improved
This commit is contained in:
@ -34,24 +34,25 @@ template<AssociatedUnit U>
|
||||
template<typename U, auto... Vs>
|
||||
[[nodiscard]] consteval auto all_are_kinds(power<U, Vs...>)
|
||||
{
|
||||
return all_are_kinds(U{});
|
||||
return decltype(all_are_kinds(U{})){};
|
||||
}
|
||||
|
||||
template<typename... Nums, typename... Dens>
|
||||
[[nodiscard]] consteval bool all_are_kinds(type_list<Nums...>, type_list<Dens...>)
|
||||
[[nodiscard]] consteval auto all_are_kinds(type_list<Nums...>, type_list<Dens...>)
|
||||
{
|
||||
return (... && all_are_kinds(Nums{})) && (... && all_are_kinds(Dens{}));
|
||||
return std::bool_constant<((... && decltype(all_are_kinds(Nums{}))::value) &&
|
||||
(... && decltype(all_are_kinds(Dens{}))::value))>{};
|
||||
}
|
||||
|
||||
template<AssociatedUnit U>
|
||||
[[nodiscard]] consteval auto all_are_kinds(U)
|
||||
{
|
||||
if constexpr (requires { U::quantity_spec; })
|
||||
return QuantityKindSpec<std::remove_const_t<decltype(U::quantity_spec)>>;
|
||||
return std::bool_constant<QuantityKindSpec<std::remove_const_t<decltype(U::quantity_spec)>>>{};
|
||||
else if constexpr (requires { U::reference_unit; })
|
||||
return all_are_kinds(U::reference_unit);
|
||||
return decltype(all_are_kinds(U::reference_unit)){};
|
||||
else if constexpr (requires { typename U::_num_; }) {
|
||||
return all_are_kinds(typename U::_num_{}, typename U::_den_{});
|
||||
return decltype(all_are_kinds(typename U::_num_{}, typename U::_den_{})){};
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,20 +68,21 @@ template<AssociatedUnit 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);
|
||||
return decltype(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);
|
||||
return decltype(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);
|
||||
constexpr bool all_kinds = decltype(all_are_kinds(u)){};
|
||||
if constexpr (all_kinds)
|
||||
return kind_of<get_associated_quantity_impl(u)>;
|
||||
return kind_of<decltype(get_associated_quantity_impl(u)){}>;
|
||||
else
|
||||
return get_associated_quantity_impl(u);
|
||||
return decltype(get_associated_quantity_impl(u)){};
|
||||
}
|
||||
|
||||
} // namespace mp_units::detail
|
||||
|
@ -26,12 +26,12 @@
|
||||
|
||||
namespace mp_units::detail {
|
||||
|
||||
[[nodiscard]] consteval std::size_t hierarchy_path_length(QuantitySpec auto q)
|
||||
[[nodiscard]] consteval auto hierarchy_path_length(QuantitySpec auto q)
|
||||
{
|
||||
if constexpr (requires { q._parent_; })
|
||||
return hierarchy_path_length(q._parent_) + 1;
|
||||
return std::integral_constant<std::size_t, decltype(hierarchy_path_length(q._parent_))::value + 1>{};
|
||||
else
|
||||
return 1;
|
||||
return std::integral_constant<std::size_t, 1>{};
|
||||
}
|
||||
|
||||
template<std::size_t Offset>
|
||||
@ -41,51 +41,53 @@ template<std::size_t Offset>
|
||||
if constexpr (Offset == 0)
|
||||
return q;
|
||||
else if constexpr (requires { q._parent_; })
|
||||
return hierarchy_path_advance<Offset - 1>(q._parent_);
|
||||
return decltype(hierarchy_path_advance<Offset - 1>(q._parent_)){};
|
||||
}
|
||||
|
||||
template<QuantitySpec A, QuantitySpec B>
|
||||
[[nodiscard]] consteval bool have_common_base_in_hierarchy_of_equal_length(A a, B b)
|
||||
[[nodiscard]] consteval auto have_common_base_in_hierarchy_of_equal_length(A a, B b)
|
||||
{
|
||||
if constexpr (is_same_v<A, B>)
|
||||
return true;
|
||||
return std::true_type{};
|
||||
else if constexpr (requires { a._parent_; })
|
||||
return have_common_base_in_hierarchy_of_equal_length(a._parent_, b._parent_);
|
||||
return decltype(have_common_base_in_hierarchy_of_equal_length(a._parent_, b._parent_)){};
|
||||
else
|
||||
return false;
|
||||
return std::false_type{};
|
||||
}
|
||||
|
||||
template<QuantitySpec A, QuantitySpec B>
|
||||
[[nodiscard]] consteval auto have_common_base(A a, B b)
|
||||
{
|
||||
constexpr std::size_t a_length = hierarchy_path_length(A{});
|
||||
constexpr std::size_t b_length = hierarchy_path_length(B{});
|
||||
constexpr std::size_t a_length = decltype(hierarchy_path_length(A{}))::value;
|
||||
constexpr std::size_t b_length = decltype(hierarchy_path_length(B{}))::value;
|
||||
if constexpr (a_length > b_length)
|
||||
return have_common_base_in_hierarchy_of_equal_length(hierarchy_path_advance<a_length - b_length>(a), b);
|
||||
return decltype(have_common_base_in_hierarchy_of_equal_length(
|
||||
decltype(hierarchy_path_advance<a_length - b_length>(a)){}, b)){};
|
||||
else
|
||||
return have_common_base_in_hierarchy_of_equal_length(a, hierarchy_path_advance<b_length - a_length>(b));
|
||||
return decltype(have_common_base_in_hierarchy_of_equal_length(
|
||||
a, decltype(hierarchy_path_advance<b_length - a_length>(b)){})){};
|
||||
}
|
||||
|
||||
template<QuantitySpec A, QuantitySpec B>
|
||||
requires(have_common_base_in_hierarchy_of_equal_length(A{}, B{}))
|
||||
[[nodiscard]] consteval auto get_common_base_for_hierarchy_of_equal_length(A a, B b)
|
||||
requires(decltype(have_common_base_in_hierarchy_of_equal_length(A{}, B{}))::value)
|
||||
[[nodiscard]] consteval QuantitySpec auto get_common_base_for_hierarchy_of_equal_length(A a, B b)
|
||||
{
|
||||
if constexpr (is_same_v<A, B>)
|
||||
return a;
|
||||
else
|
||||
return get_common_base_for_hierarchy_of_equal_length(a._parent_, b._parent_);
|
||||
return decltype(get_common_base_for_hierarchy_of_equal_length(a._parent_, b._parent_)){};
|
||||
}
|
||||
|
||||
template<QuantitySpec A, QuantitySpec B>
|
||||
requires(have_common_base(A{}, B{}))
|
||||
[[nodiscard]] consteval auto get_common_base(A a, B b)
|
||||
requires(decltype(have_common_base(A{}, B{}))::value)
|
||||
[[nodiscard]] consteval QuantitySpec auto get_common_base(A a, B b)
|
||||
{
|
||||
constexpr int a_length = hierarchy_path_length(A{});
|
||||
constexpr int b_length = hierarchy_path_length(B{});
|
||||
constexpr std::size_t a_length = decltype(hierarchy_path_length(A{}))::value;
|
||||
constexpr std::size_t b_length = decltype(hierarchy_path_length(B{}))::value;
|
||||
if constexpr (a_length > b_length)
|
||||
return get_common_base_for_hierarchy_of_equal_length(hierarchy_path_advance<a_length - b_length>(a), b);
|
||||
return decltype(get_common_base_for_hierarchy_of_equal_length(hierarchy_path_advance<a_length - b_length>(a), b)){};
|
||||
else
|
||||
return get_common_base_for_hierarchy_of_equal_length(a, hierarchy_path_advance<b_length - a_length>(b));
|
||||
return decltype(get_common_base_for_hierarchy_of_equal_length(a, hierarchy_path_advance<b_length - a_length>(b))){};
|
||||
}
|
||||
|
||||
template<QuantitySpec Child, QuantitySpec Parent>
|
||||
@ -94,8 +96,8 @@ template<QuantitySpec Child, QuantitySpec Parent>
|
||||
if constexpr (Child{} == Parent{})
|
||||
return std::true_type{};
|
||||
else {
|
||||
constexpr auto child_length = hierarchy_path_length(Child{});
|
||||
constexpr auto parent_length = hierarchy_path_length(Parent{});
|
||||
constexpr std::size_t child_length = decltype(hierarchy_path_length(Child{}))::value;
|
||||
constexpr std::size_t parent_length = decltype(hierarchy_path_length(Parent{}))::value;
|
||||
if constexpr (parent_length > child_length)
|
||||
return std::false_type{};
|
||||
else
|
||||
|
@ -46,7 +46,7 @@ MP_UNITS_EXPORT_BEGIN
|
||||
|
||||
[[nodiscard]] consteval QuantitySpec auto get_quantity_spec(AssociatedUnit auto u)
|
||||
{
|
||||
return detail::get_associated_quantity(u);
|
||||
return decltype(detail::get_associated_quantity(u)){};
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user