feat: quantity_point support added for quantity_cast and value_cast

This commit is contained in:
Mateusz Pusz
2023-12-18 16:40:05 +01:00
parent bd9e4f944c
commit ce6db6950f
2 changed files with 64 additions and 0 deletions

View File

@@ -23,6 +23,7 @@
#pragma once
#include <mp-units/bits/quantity_concepts.h>
#include <mp-units/bits/quantity_point_concepts.h>
#include <mp-units/reference.h>
#include <type_traits>
@@ -56,4 +57,29 @@ template<QuantitySpec auto ToQS, typename Q>
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_, reference<ToQS, Q::unit>{}};
}
/**
* @brief Explicit cast of a quantity point type
*
* This cast converts only a quantity point type. It might be used to force some quantity point type
* conversions that are not implicitly allowed but are allowed explicitly.
*
* For example:
*
* @code{.cpp}
* auto length = isq::length(quantity_point{42 * m});
* auto altitude = quantity_cast<isq::altitude>(length);
* @endcode
*
* @note This cast does not affect the underlying value of a number stored in a quantity point.
*
* @tparam ToQS a quantity specification to use for a target quantity point
*/
template<QuantitySpec auto ToQS, typename QP>
requires QuantityPoint<std::remove_cvref_t<QP>> && (castable(QP::quantity_spec, ToQS))
[[nodiscard]] constexpr QuantityPoint auto quantity_cast(QP&& qp)
{
return QP{quantity_cast<ToQS>(std::forward<QP>(qp).quantity_from_origin_is_an_implementation_detail_),
qp.point_origin};
}
} // namespace mp_units

View File

@@ -23,6 +23,7 @@
#pragma once
#include <mp-units/bits/quantity_concepts.h>
#include <mp-units/bits/quantity_point_concepts.h>
#include <mp-units/bits/representation_concepts.h>
#include <mp-units/bits/sudo_cast.h>
#include <mp-units/bits/unit_concepts.h>
@@ -74,4 +75,41 @@ template<Representation ToRep, typename Q>
return detail::sudo_cast<quantity<std::remove_reference_t<Q>::reference, ToRep>>(std::forward<Q>(q));
}
/**
* @brief Explicit cast of a quantity point's unit
*
* Implicit conversions between quantity points of different types are allowed only for "safe"
* (e.g. non-truncating) conversion. In truncating cases an explicit cast have to be used.
*
* auto qp = value_cast<si::second>(quantity_point{1234 * ms});
*
* @tparam ToU a unit to use for a target quantity point
*/
template<Unit auto ToU, typename QP>
[[nodiscard]] constexpr QuantityPoint auto value_cast(QP&& qp)
requires QuantityPoint<std::remove_cvref_t<QP>> && (convertible(std::remove_reference_t<QP>::reference, ToU))
{
return QP{value_cast<ToU>(std::forward<QP>(qp).quantity_from_origin_is_an_implementation_detail_), qp.point_origin};
}
/**
* @brief Explicit cast of a quantity point's representation type
*
* Implicit conversions between quantity points of different types are allowed only for "safe"
* (e.g. non-truncating) conversion. In truncating cases an explicit cast have to be used.
*
* auto qp = value_cast<int>(quantity_point{1.23 * ms});
*
* @tparam ToRep a representation type to use for a target quantity point
*/
template<Representation ToRep, typename QP>
requires QuantityPoint<std::remove_cvref_t<QP>> &&
RepresentationOf<ToRep, std::remove_reference_t<QP>::quantity_spec.character> &&
std::constructible_from<ToRep, typename std::remove_reference_t<QP>::rep>
[[nodiscard]] constexpr quantity_point<std::remove_reference_t<QP>::reference, QP::point_origin, ToRep> value_cast(
QP&& qp)
{
return {value_cast<ToRep>(std::forward<QP>(qp).quantity_from_origin_is_an_implementation_detail_), qp.point_origin};
}
} // namespace mp_units