diff --git a/src/core/include/mp_units/quantity_spec.h b/src/core/include/mp_units/quantity_spec.h index db040d54..c5162aca 100644 --- a/src/core/include/mp_units/quantity_spec.h +++ b/src/core/include/mp_units/quantity_spec.h @@ -155,6 +155,9 @@ template #endif struct quantity_spec; +inline constexpr struct is_kind { +} is_kind; + /** * @brief Specialization defining a base quantity * @@ -236,7 +239,7 @@ template>) struct quantity_spec : detail::quantity_spec_interface { #else -template +template auto... Args> requires(... && !QuantitySpec>) struct quantity_spec : detail::quantity_spec_interface { #endif @@ -270,13 +273,14 @@ struct quantity_spec : detail::quantity_spec_interface * * @tparam Q quantity specification of a parent quantity * @tparam Args optionally a value of a `quantity_character` in case the base quantity should not be scalar + * or `is_kind` in case the quantity starts a new hierarchy tree of a kind */ #ifdef __cpp_explicit_this_parameter -template auto... Args> +template auto... Args> requires(... && !QuantitySpec>) -struct quantity_spec : std::remove_const_t { +struct quantity_spec : std::remove_const_t { #else -template +template auto... Args> requires(... && !QuantitySpec>) struct quantity_spec : std::remove_const_t { #endif @@ -325,17 +329,18 @@ struct quantity_spec : std::remove_const_t { * * @tparam Q quantity specification of a parent quantity * @tparam Args optionally a value of a `quantity_character` in case the base quantity should not be scalar + * or `is_kind` in case the quantity starts a new hierarchy tree of a kind */ #ifdef __cpp_explicit_this_parameter template auto... Args> + one_of auto... Args> requires(!requires { QS._equation_; } || (requires { QS._equation_; } && (explicitly_convertible(Eq, QS._equation_)))) && (... && !QuantitySpec>) struct quantity_spec : quantity_spec { #else template + one_of auto... Args> requires(!requires { QS._equation_; } || (requires { QS._equation_; } && (explicitly_convertible(Eq, QS._equation_)))) && (... && !QuantitySpec>) @@ -443,7 +448,6 @@ template requires(get_kind(Q) == Q) inline constexpr kind_of_ kind_of; - namespace detail { template<> @@ -589,7 +593,7 @@ template requires requires { Q::_equation_; } [[nodiscard]] consteval bool defines_equation(Q) { - if constexpr (requires { Q::_parent_; }) + if constexpr (requires { Q::_parent_._equation_; }) return Q::_parent_._equation_ != Q::_equation_; else return true; @@ -1263,14 +1267,14 @@ template else return convertible_impl(from_kind, get_kind(explode(to_kind).quantity)); } else if constexpr (NamedQuantitySpec && NamedQuantitySpec) { - if constexpr (get_kind(from) != get_kind(to)) - return no; - else if constexpr (have_common_base(from, to)) { + if constexpr (have_common_base(from, to)) { if (std::derived_from) return yes; else return std::derived_from ? explicit_conversion : cast; - } else if constexpr (get_complexity(from) != get_complexity(to)) { + } else if constexpr (get_kind(from) != get_kind(to)) + return no; + else if constexpr (get_complexity(from) != get_complexity(to)) { if constexpr (get_complexity(from) > get_complexity(to)) return convertible_impl(explode(from).quantity, to); else { @@ -1327,8 +1331,19 @@ template requires requires(Q q) { get_kind(q); } using to_kind = std::remove_const_t; +#ifdef __cpp_explicit_this_parameter +template +[[nodiscard]] consteval bool defined_as_kind(quantity_spec) +#else +template +[[nodiscard]] consteval bool defined_as_kind(quantity_spec) +#endif +{ + return contains(); } +} // namespace detail + template [[nodiscard]] consteval auto remove_kind(Q q) { @@ -1344,8 +1359,17 @@ template template [[nodiscard]] consteval QuantitySpec auto get_kind(Q q) { + auto defined_as_kind = [](auto qq) { + if constexpr (requires { detail::defined_as_kind(qq); }) + return detail::defined_as_kind(qq); + else + return false; + }; + if constexpr (QuantityKindSpec) { return remove_kind(q); + } else if constexpr (defined_as_kind(q)) { + return q; } else if constexpr (requires { Q::_parent_; }) { return get_kind(Q::_parent_); } else if constexpr (detail::IntermediateDerivedQuantitySpec) {