mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-07 06:04:27 +02:00
feat: UnitCompatibleWith
added and applied to in(U)
and force_in(U)
functions
This commit is contained in:
@@ -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.
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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>)
|
||||
|
Reference in New Issue
Block a user