feat: UnitCompatibleWith added and applied to in(U) and force_in(U) functions

This commit is contained in:
Mateusz Pusz
2023-09-27 17:06:08 +02:00
parent 969bf9716c
commit b4bb7227b9
5 changed files with 36 additions and 7 deletions

View File

@@ -263,13 +263,23 @@ concept with an associated quantity type implicitly convertible to `V`.
[nested quantity kind within the dimensionless quantities tree](dimensionless_quantities.md/#nested-quantity-kinds).
### `UnitCompatibleWith<T, V1, V2>` { #UnitCompatibleWith }
`UnitCompatibleWith` concept is satisfied for all units `T` when:
- `V1` is a [`Unit`](#Unit),
- `V2` is a [`QuantitySpec`](#QuantitySpec),
- `T` and `V1` are defined in terms of the same reference unit,
- if `T` is an [`AssociatedUnit`](#AssociatedUnit) it should satisfy [`UnitOf<V2>`](#UnitOf).
## `Reference<T>` { #Reference }
`Reference` concept is satisfied by all [quantity reference](../../appendix/glossary.md#reference)
types. Such types provide all the meta-information required to create a [`Quantity`](#Quantity).
A `Reference` can either be:
- An [AssociatedUnit](#AssociatedUnit).
- An [`AssociatedUnit`](#AssociatedUnit).
- The instantiation of a `reference` class template with a [`QuantitySpec`](#QuantitySpec) passed as
the first template argument and a [`Unit`](#Unit) passed as the second one.

View File

@@ -193,4 +193,22 @@ concept UnitOf =
// 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 detail {
[[nodiscard]] consteval bool have_same_canonical_reference_unit(Unit auto u1, Unit auto u2);
}
/**
* @brief A concept matching all units compatible with the provided unit and quantity spec
*
* Satisfied by all units that have the same canonical reference as `U2` and in case they
* have associated quantity specification it should satisfy `UnitOf<QS>`.
*/
template<typename U, auto U2, auto QS>
concept UnitCompatibleWith =
Unit<U> && Unit<std::remove_const_t<decltype(U2)>> && QuantitySpec<std::remove_const_t<decltype(QS)>> &&
(!AssociatedUnit<U> || UnitOf<U, QS>)&&detail::have_same_canonical_reference_unit(U{}, U2);
} // namespace mp_units

View File

@@ -142,14 +142,14 @@ public:
quantity& operator=(quantity&&) = default;
// conversions
template<Unit U>
template<UnitCompatibleWith<unit, quantity_spec> U>
requires detail::QuantityConvertibleTo<quantity, quantity<detail::make_reference(quantity_spec, U{}), Rep>>
[[nodiscard]] constexpr quantity<detail::make_reference(quantity_spec, U{}), Rep> in(U) const
{
return quantity<detail::make_reference(quantity_spec, U{}), Rep>{*this};
}
template<Unit U>
template<UnitCompatibleWith<unit, quantity_spec> U>
requires requires(quantity q) { value_cast<U{}>(q); }
[[nodiscard]] constexpr quantity<detail::make_reference(quantity_spec, U{}), Rep> force_in(U) const
{
@@ -175,14 +175,14 @@ public:
requires(U{} == unit)
constexpr const rep&& numerical_value_ref_in(U) const&& noexcept = delete;
template<Unit U>
template<UnitCompatibleWith<unit, quantity_spec> U>
requires requires(quantity q) { q.in(U{}); }
[[nodiscard]] constexpr rep numerical_value_in(U) const noexcept
{
return (*this).in(U{}).numerical_value_;
}
template<Unit U>
template<UnitCompatibleWith<unit, quantity_spec> U>
requires requires(quantity q) { q.force_in(U{}); }
[[nodiscard]] constexpr rep force_numerical_value_in(U) const noexcept
{

View File

@@ -168,14 +168,14 @@ public:
return *this - PO2{};
}
template<Unit U>
template<UnitCompatibleWith<unit, quantity_spec> U>
requires detail::QuantityConvertibleTo<quantity_type, quantity<detail::make_reference(quantity_spec, U{}), Rep>>
[[nodiscard]] constexpr quantity_point<detail::make_reference(quantity_spec, U{}), PO, Rep> in(U) const
{
return make_quantity_point<PO>(quantity_ref_from(PO).in(U{}));
}
template<Unit U>
template<UnitCompatibleWith<unit, quantity_spec> U>
requires requires(quantity_type q) { value_cast<U{}>(q); }
[[nodiscard]] constexpr quantity_point<detail::make_reference(quantity_spec, U{}), PO, Rep> force_in(U) const
{

View File

@@ -40,6 +40,7 @@ namespace detail {
template<QuantitySpec QS, Unit U>
requires(!AssociatedUnit<U>) || UnitOf<U, QS{}>
[[nodiscard]] consteval Reference auto make_reference(QS qs, U u)
{
if constexpr (detail::QuantityKindSpec<QS>)