diff --git a/docs/users_guide/framework_basics/value_conversions.md b/docs/users_guide/framework_basics/value_conversions.md index 1ec7e340..96181fd2 100644 --- a/docs/users_guide/framework_basics/value_conversions.md +++ b/docs/users_guide/framework_basics/value_conversions.md @@ -182,11 +182,11 @@ which may well be outside the range of one or both quantity types. The table below provides all the value conversions functions that may be run on `x` being the instance of either `quantity` or `quantity_point`: -| Forcing | Representation | Unit | Member function | Conversion function | -|:-------:|:--------------:|:----:|--------------------|-----------------------| -| No | Same | `u` | `x.in(u)` | | -| No | `T` | Same | `x.in()` | | -| No | `T` | `u` | `x.in(u)` | | -| Yes | Same | `u` | `x.force_in(u)` | `value_cast(x)` | -| Yes | `T` | Same | `x.force_in()` | `value_cast(x)` | -| Yes | `T` | `u` | `x.force_in(u)` | `value_cast(x)` | +| Forcing | Representation | Unit | Member function | Non-member function | +|:-------:|:--------------:|:----:|--------------------|------------------------------------------------| +| No | Same | `u` | `x.in(u)` | | +| No | `T` | Same | `x.in()` | | +| No | `T` | `u` | `x.in(u)` | | +| Yes | Same | `u` | `x.force_in(u)` | `value_cast(x)` | +| Yes | `T` | Same | `x.force_in()` | `value_cast(x)` | +| Yes | `T` | `u` | `x.force_in(u)` | `value_cast(x)` or `value_cast(x)` | diff --git a/src/core/include/mp-units/framework/value_cast.h b/src/core/include/mp-units/framework/value_cast.h index d5ebf69e..5fe64373 100644 --- a/src/core/include/mp-units/framework/value_cast.h +++ b/src/core/include/mp-units/framework/value_cast.h @@ -88,6 +88,14 @@ template>(std::forward(q)); } +template> + requires(convertible(Q::reference, ToU)) && RepresentationOf && + std::constructible_from +[[nodiscard]] constexpr Quantity auto value_cast(FwdQ&& q) +{ + return detail::sudo_cast>(std::forward(q)); +} + /** * @brief Explicit cast of a quantity's representation @@ -168,6 +176,16 @@ template> + requires(convertible(QP::reference, ToU)) && RepresentationOf && + std::constructible_from +[[nodiscard]] constexpr QuantityPoint auto value_cast(FwdQP&& qp) +{ + return quantity_point{ + value_cast(std::forward(qp).quantity_from_origin_is_an_implementation_detail_), + QP::point_origin}; +} + /** * @brief Explicit cast of a quantity point's representation * diff --git a/test/static/quantity_point_test.cpp b/test/static/quantity_point_test.cpp index f04e9c1a..2a86878a 100644 --- a/test/static/quantity_point_test.cpp +++ b/test/static/quantity_point_test.cpp @@ -1725,6 +1725,7 @@ constexpr quantity_point lvalue_qp{2 * km}; static_assert(value_cast(lvalue_qp).quantity_from_zero().numerical_value_in(m) == 2000); static_assert(value_cast(lvalue_qp).quantity_from_zero().numerical_value_in(km) == 2.f); static_assert(value_cast(lvalue_qp).quantity_from_zero().numerical_value_in(m) == 2000.f); +static_assert(value_cast(lvalue_qp).quantity_from_zero().numerical_value_in(m) == 2000.f); } // namespace lvalue_tests static_assert(value_cast>(quantity_point{2000 * m}).quantity_from_zero().numerical_value_in(km) == 2); diff --git a/test/static/quantity_test.cpp b/test/static/quantity_test.cpp index 89f169bb..6df1602a 100644 --- a/test/static/quantity_test.cpp +++ b/test/static/quantity_test.cpp @@ -1014,6 +1014,7 @@ static_assert(value_cast(2000.0 * m / (3600.0 * s)).numerical_value_in(k static_assert(value_cast(1.23 * m).numerical_value_in(m) == 1); static_assert(value_cast(1.23 * m).numerical_value_in(km) == 0); +static_assert(value_cast(1.23 * m).numerical_value_in(km) == 0); static_assert((2 * km).force_in(m).numerical_value_in(m) == 2000); static_assert((2000 * m).force_in(km).numerical_value_in(km) == 2);