refactor: get_associated_quantity and quantity spec hierarchy traversing compile-times improved

This commit is contained in:
Mateusz Pusz
2024-06-13 12:29:12 +02:00
parent 5f67523a8a
commit f63c4eec4a
3 changed files with 39 additions and 35 deletions

View File

@ -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

View File

@ -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

View File

@ -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)){};
}
/**