mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-01 03:14:29 +02:00
feat: DimensionOf
and QuantitySpecOf
added and reused in ReferenceOf
concept
This commit is contained in:
@@ -101,4 +101,12 @@ concept DerivedDimension = is_derived_from_specialization_of<T, derived_dimensio
|
||||
template<typename T>
|
||||
concept Dimension = detail::BaseDimension<T> || detail::DerivedDimension<T>;
|
||||
|
||||
/**
|
||||
* @brief A concept checking if the argument is of the same dimension.
|
||||
*
|
||||
* Satisfied when both argument satisfy a `Dimension` concept and when they compare equal.
|
||||
*/
|
||||
template<typename T, auto D>
|
||||
concept DimensionOf = Dimension<T> && Dimension<std::remove_const_t<decltype(D)>> && (T{} == D);
|
||||
|
||||
} // namespace mp_units
|
||||
|
@@ -157,11 +157,23 @@ template<QuantitySpec Q>
|
||||
namespace detail {
|
||||
|
||||
template<auto To, auto From>
|
||||
concept DerivedFromQuantityKindSpecOf =
|
||||
concept NestedQuantityKindSpecOf =
|
||||
QuantitySpec<std::remove_const_t<decltype(From)>> && QuantitySpec<std::remove_const_t<decltype(To)>> &&
|
||||
get_kind(From) != get_kind(To) &&
|
||||
std::derived_from<std::remove_cvref_t<decltype(To)>, std::remove_cvref_t<decltype(get_kind(From))>>;
|
||||
|
||||
}
|
||||
|
||||
template<typename T, auto QS>
|
||||
concept QuantitySpecOf =
|
||||
QuantitySpec<T> && QuantitySpec<std::remove_const_t<decltype(QS)>> && implicitly_convertible(T{}, QS) &&
|
||||
// the below is to make the following work
|
||||
// static_assert(ReferenceOf<si::radian, isq::angular_measure>);
|
||||
// static_assert(!ReferenceOf<si::radian, dimensionless>);
|
||||
// static_assert(!ReferenceOf<isq::angular_measure[si::radian], dimensionless>
|
||||
// static_assert(ReferenceOf<one, isq::angular_measure>);
|
||||
// static_assert(!ReferenceOf<dimensionless[one], isq::angular_measure>);
|
||||
!detail::NestedQuantityKindSpecOf<T{}, QS> &&
|
||||
(detail::QuantityKindSpec<T> || !detail::NestedQuantityKindSpecOf<QS, T{}>);
|
||||
|
||||
} // namespace mp_units
|
||||
|
@@ -72,11 +72,7 @@ template<auto Q, auto U>
|
||||
*/
|
||||
template<typename T, auto V>
|
||||
concept ReferenceOf =
|
||||
Reference<T> &&
|
||||
((Dimension<std::remove_const_t<decltype(V)>> && get_quantity_spec(T{}).dimension == V) ||
|
||||
(QuantitySpec<std::remove_const_t<decltype(V)>> && implicitly_convertible(get_quantity_spec(T{}), V) &&
|
||||
!detail::DerivedFromQuantityKindSpecOf<get_quantity_spec(T{}), V> &&
|
||||
(detail::QuantityKindSpec<std::remove_const_t<decltype(get_quantity_spec(T{}))>> ||
|
||||
!detail::DerivedFromQuantityKindSpecOf<V, get_quantity_spec(T{})>)));
|
||||
Reference<T> && (DimensionOf<std::remove_const_t<decltype(get_quantity_spec(T{}).dimension)>, V> ||
|
||||
QuantitySpecOf<std::remove_const_t<decltype(get_quantity_spec(T{}))>, V>);
|
||||
|
||||
} // namespace mp_units
|
||||
|
@@ -185,10 +185,10 @@ concept AssociatedUnit = Unit<U> && detail::has_associated_quantity(U{});
|
||||
* the provided quantity_spec type.
|
||||
*/
|
||||
template<typename U, auto QS>
|
||||
concept UnitOf = AssociatedUnit<U> && QuantitySpec<std::remove_const_t<decltype(QS)>> &&
|
||||
implicitly_convertible(get_quantity_spec(U{}), QS) &&
|
||||
// the below is to make `dimensionless[radian]` invalid
|
||||
(get_kind(QS) == get_kind(get_quantity_spec(U{})) ||
|
||||
!detail::DerivedFromQuantityKindSpecOf<get_quantity_spec(U{}), QS>);
|
||||
concept UnitOf =
|
||||
AssociatedUnit<U> && QuantitySpec<std::remove_const_t<decltype(QS)>> &&
|
||||
implicitly_convertible(get_quantity_spec(U{}), QS) &&
|
||||
// the below is to make `dimensionless[radian]` invalid
|
||||
(get_kind(QS) == get_kind(get_quantity_spec(U{})) || !detail::NestedQuantityKindSpecOf<get_quantity_spec(U{}), QS>);
|
||||
|
||||
} // namespace mp_units
|
||||
|
@@ -1354,7 +1354,7 @@ template<QuantitySpec From, QuantitySpec To>
|
||||
else
|
||||
return exploded_kind_result(
|
||||
convertible_impl(from_kind, get_kind(explode<get_complexity(from_kind)>(to_kind).quantity)));
|
||||
} else if constexpr (DerivedFromQuantityKindSpecOf<get_kind(to), from> && get_kind(to) == to)
|
||||
} else if constexpr (NestedQuantityKindSpecOf<get_kind(to), from> && get_kind(to) == to)
|
||||
return yes;
|
||||
else if constexpr (NamedQuantitySpec<From> && NamedQuantitySpec<To>) {
|
||||
if constexpr (have_common_base(from, to)) {
|
||||
@@ -1481,9 +1481,9 @@ template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
using QQ2 = std::remove_const_t<decltype(remove_kind(q2))>;
|
||||
if constexpr (is_same_v<Q1, Q2>)
|
||||
return q1;
|
||||
else if constexpr (detail::DerivedFromQuantityKindSpecOf<q1, q2>)
|
||||
else if constexpr (detail::NestedQuantityKindSpecOf<q1, q2>)
|
||||
return remove_kind(q1);
|
||||
else if constexpr (detail::DerivedFromQuantityKindSpecOf<q2, q1>)
|
||||
else if constexpr (detail::NestedQuantityKindSpecOf<q2, q1>)
|
||||
return remove_kind(q2);
|
||||
else if constexpr ((detail::QuantityKindSpec<Q1> && !detail::QuantityKindSpec<Q2>) ||
|
||||
(detail::IntermediateDerivedQuantitySpec<QQ1> && detail::NamedQuantitySpec<QQ2> &&
|
||||
|
@@ -792,6 +792,7 @@ static_assert((velocity / acceleration).character == quantity_character::scalar)
|
||||
|
||||
// common_quantity_spec
|
||||
static_assert(common_quantity_spec(length, length) == length);
|
||||
static_assert(common_quantity_spec(kind_of<length>, kind_of<length>) == kind_of<length>);
|
||||
static_assert(common_quantity_spec(kind_of<length>, length) == length);
|
||||
static_assert(common_quantity_spec(length, kind_of<length>) == length);
|
||||
static_assert(common_quantity_spec(width, kind_of<length>) == width);
|
||||
|
Reference in New Issue
Block a user