forked from mpusz/mp-units
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).
|
[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<T>` { #Reference }
|
||||||
|
|
||||||
`Reference` concept is satisfied by all [quantity reference](../../appendix/glossary.md#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).
|
types. Such types provide all the meta-information required to create a [`Quantity`](#Quantity).
|
||||||
A `Reference` can either be:
|
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 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.
|
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
|
// the below is to make `dimensionless[radian]` invalid
|
||||||
(get_kind(QS) == get_kind(get_quantity_spec(U{})) || !detail::NestedQuantityKindSpecOf<get_quantity_spec(U{}), QS>);
|
(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
|
} // namespace mp_units
|
||||||
|
@@ -142,14 +142,14 @@ public:
|
|||||||
quantity& operator=(quantity&&) = default;
|
quantity& operator=(quantity&&) = default;
|
||||||
|
|
||||||
// conversions
|
// conversions
|
||||||
template<Unit U>
|
template<UnitCompatibleWith<unit, quantity_spec> U>
|
||||||
requires detail::QuantityConvertibleTo<quantity, quantity<detail::make_reference(quantity_spec, U{}), Rep>>
|
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
|
[[nodiscard]] constexpr quantity<detail::make_reference(quantity_spec, U{}), Rep> in(U) const
|
||||||
{
|
{
|
||||||
return quantity<detail::make_reference(quantity_spec, U{}), Rep>{*this};
|
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); }
|
requires requires(quantity q) { value_cast<U{}>(q); }
|
||||||
[[nodiscard]] constexpr quantity<detail::make_reference(quantity_spec, U{}), Rep> force_in(U) const
|
[[nodiscard]] constexpr quantity<detail::make_reference(quantity_spec, U{}), Rep> force_in(U) const
|
||||||
{
|
{
|
||||||
@@ -175,14 +175,14 @@ public:
|
|||||||
requires(U{} == unit)
|
requires(U{} == unit)
|
||||||
constexpr const rep&& numerical_value_ref_in(U) const&& noexcept = delete;
|
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{}); }
|
requires requires(quantity q) { q.in(U{}); }
|
||||||
[[nodiscard]] constexpr rep numerical_value_in(U) const noexcept
|
[[nodiscard]] constexpr rep numerical_value_in(U) const noexcept
|
||||||
{
|
{
|
||||||
return (*this).in(U{}).numerical_value_;
|
return (*this).in(U{}).numerical_value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Unit U>
|
template<UnitCompatibleWith<unit, quantity_spec> U>
|
||||||
requires requires(quantity q) { q.force_in(U{}); }
|
requires requires(quantity q) { q.force_in(U{}); }
|
||||||
[[nodiscard]] constexpr rep force_numerical_value_in(U) const noexcept
|
[[nodiscard]] constexpr rep force_numerical_value_in(U) const noexcept
|
||||||
{
|
{
|
||||||
|
@@ -168,14 +168,14 @@ public:
|
|||||||
return *this - PO2{};
|
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>>
|
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
|
[[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{}));
|
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); }
|
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
|
[[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>
|
template<QuantitySpec QS, Unit U>
|
||||||
|
requires(!AssociatedUnit<U>) || UnitOf<U, QS{}>
|
||||||
[[nodiscard]] consteval Reference auto make_reference(QS qs, U u)
|
[[nodiscard]] consteval Reference auto make_reference(QS qs, U u)
|
||||||
{
|
{
|
||||||
if constexpr (detail::QuantityKindSpec<QS>)
|
if constexpr (detail::QuantityKindSpec<QS>)
|
||||||
|
Reference in New Issue
Block a user