From ce6db6950fe75e30a3a536cfa3cd938d8dfb436b Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Mon, 18 Dec 2023 16:40:05 +0100 Subject: [PATCH] feat: `quantity_point` support added for `quantity_cast` and `value_cast` --- .../include/mp-units/bits/quantity_cast.h | 26 +++++++++++++ src/core/include/mp-units/bits/value_cast.h | 38 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/core/include/mp-units/bits/quantity_cast.h b/src/core/include/mp-units/bits/quantity_cast.h index b03c7ea3..cf8fbef9 100644 --- a/src/core/include/mp-units/bits/quantity_cast.h +++ b/src/core/include/mp-units/bits/quantity_cast.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include #include @@ -56,4 +57,29 @@ template return quantity{std::forward(q).numerical_value_is_an_implementation_detail_, reference{}}; } +/** + * @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(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 + requires QuantityPoint> && (castable(QP::quantity_spec, ToQS)) +[[nodiscard]] constexpr QuantityPoint auto quantity_cast(QP&& qp) +{ + return QP{quantity_cast(std::forward(qp).quantity_from_origin_is_an_implementation_detail_), + qp.point_origin}; +} + } // namespace mp_units diff --git a/src/core/include/mp-units/bits/value_cast.h b/src/core/include/mp-units/bits/value_cast.h index 7d045163..88316ad8 100644 --- a/src/core/include/mp-units/bits/value_cast.h +++ b/src/core/include/mp-units/bits/value_cast.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include #include #include @@ -74,4 +75,41 @@ template return detail::sudo_cast::reference, ToRep>>(std::forward(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(quantity_point{1234 * ms}); + * + * @tparam ToU a unit to use for a target quantity point + */ +template +[[nodiscard]] constexpr QuantityPoint auto value_cast(QP&& qp) + requires QuantityPoint> && (convertible(std::remove_reference_t::reference, ToU)) +{ + return QP{value_cast(std::forward(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(quantity_point{1.23 * ms}); + * + * @tparam ToRep a representation type to use for a target quantity point + */ +template + requires QuantityPoint> && + RepresentationOf::quantity_spec.character> && + std::constructible_from::rep> +[[nodiscard]] constexpr quantity_point::reference, QP::point_origin, ToRep> value_cast( + QP&& qp) +{ + return {value_cast(std::forward(qp).quantity_from_origin_is_an_implementation_detail_), qp.point_origin}; +} + } // namespace mp_units