mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-30 18:37:15 +02:00
feat: two argument explicit cast support added
This commit is contained in:
@ -78,16 +78,21 @@ Quantity Cast Overloads
|
||||
:linenos:
|
||||
|
||||
std::cout << "Distance: " << quantity_cast<si::length<si::metre, int>>(d) << '\n';
|
||||
std::cout << "Distance: " << quantity_cast<si::dim_length>(d) << '\n';
|
||||
std::cout << "Distance: " << quantity_cast<si::metre>(d) << '\n';
|
||||
std::cout << "Distance: " << quantity_cast<int>(d) << '\n';
|
||||
std::cout << "Distance: " << quantity_cast<si::dim_length, si::metre>(d) << '\n';
|
||||
|
||||
`quantity_cast` in line #1 takes a specific target `quantity` type to which an explicit
|
||||
cast should be performed. This option will change multiple quantity properties at once
|
||||
(unit, representation, etc). However, it is also possible to force only one property at
|
||||
(unit, representation, etc). However, it is also possible to force only some properties at
|
||||
once and leave the rest intact:
|
||||
|
||||
- line #2 forces only a specific destination unit type,
|
||||
- line #3 sets only a representation type to the type provided by the user.
|
||||
- line #2 forces only a specific destination dimension type,
|
||||
- line #3 forces only a specific destination unit type,
|
||||
- line #4 sets only a representation type to the type provided by the user,
|
||||
- line #5 forces both a specific dimension and a unit while preserving the original
|
||||
representation type.
|
||||
|
||||
`quantity_point_cast` takes anything that works for `quantity_point`
|
||||
or a specific target `quantity_point`::
|
||||
|
@ -37,7 +37,11 @@ int main()
|
||||
using namespace units::physical::si::literals;
|
||||
Speed auto v1 = avg_speed(220_q_km, 2_q_h);
|
||||
Speed auto v2 = avg_speed(si::length<international::mile>(140), si::time<si::hour>(2));
|
||||
#if DOWNCAST_MODE == 0
|
||||
Speed auto v3 = quantity_cast<si::dim_speed, si::metre_per_second>(v2);
|
||||
#else
|
||||
Speed auto v3 = quantity_cast<si::metre_per_second>(v2);
|
||||
#endif
|
||||
Speed auto v4 = quantity_cast<int>(v3);
|
||||
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
|
@ -131,7 +131,11 @@ void example()
|
||||
const auto t = si::time<si::second, measurement<double>>(measurement(1.2, 0.1));
|
||||
|
||||
const Speed auto v1 = a * t;
|
||||
#if DOWNCAST_MODE == 0
|
||||
std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::dim_speed, si::kilometre_per_hour>(v1) << '\n';
|
||||
#else
|
||||
std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::kilometre_per_hour>(v1) << '\n';
|
||||
#endif
|
||||
|
||||
si::length<si::metre, measurement<double>> length(measurement(123., 1.));
|
||||
std::cout << "10 * " << length << " = " << 10 * length << '\n';
|
||||
|
@ -301,7 +301,7 @@ constexpr ratio cast_ratio(const Q1& from, const Q2& to)
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @brief Explcit cast of a quantity
|
||||
* @brief Explicit cast of a quantity
|
||||
*
|
||||
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||
@ -325,7 +325,7 @@ template<Quantity To, typename D, typename U, typename Rep>
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Explcit cast of a quantity
|
||||
* @brief Explicit cast of a quantity
|
||||
*
|
||||
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||
@ -344,7 +344,7 @@ template<Dimension ToD, typename D, typename U, typename Rep>
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Explcit cast of a quantity
|
||||
* @brief Explicit cast of a quantity
|
||||
*
|
||||
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||
@ -363,7 +363,30 @@ template<Unit ToU, typename D, typename U, typename Rep>
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Explcit cast of a quantity
|
||||
* @brief Explicit cast of a quantity
|
||||
*
|
||||
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||
*
|
||||
* This cast gets both the target dimension and unit to cast to. For example:
|
||||
*
|
||||
* auto q1 = units::quantity_cast<units::physical::si::dim_speed, units::physical::si::kilometre_per_hour>(v1);
|
||||
*
|
||||
* @note This cast is especially useful when working with quantities of unknown dimensions
|
||||
* (@c unknown_dimension).
|
||||
*
|
||||
* @tparam ToD a dimension type to use for a target quantity
|
||||
* @tparam ToU a unit type to use for a target quantity
|
||||
*/
|
||||
template<Dimension ToD, Unit ToU, typename D, typename U, typename Rep>
|
||||
requires equivalent<ToD, D> && UnitOf<ToU, ToD>
|
||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||
{
|
||||
return quantity_cast<quantity<ToD, ToU, Rep>>(q);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Explicit cast of a quantity
|
||||
*
|
||||
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||
@ -381,7 +404,7 @@ template<ScalableNumber ToRep, typename D, typename U, typename Rep>
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Explcit cast of a quantity point
|
||||
* @brief Explicit cast of a quantity point
|
||||
*
|
||||
* Implicit conversions between quantity points of different types are allowed only for "safe"
|
||||
* (i.e. non-truncating) conversion. In other cases an explicit cast has to be used.
|
||||
@ -407,6 +430,29 @@ template<typename CastSpec, typename D, typename U, typename Rep>
|
||||
return quantity_point(quantity_cast<CastSpec>(qp.relative()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Explicit cast of a quantity point
|
||||
*
|
||||
* Implicit conversions between quantity points of different types are allowed only for "safe"
|
||||
* (i.e. non-truncating) conversion. In other cases an explicit cast has to be used.
|
||||
*
|
||||
* This cast gets both the target dimension and unit to cast to. For example:
|
||||
*
|
||||
* auto q1 = units::quantity_point_cast<units::physical::si::dim_speed, units::physical::si::kilometre_per_hour>(v1);
|
||||
*
|
||||
* @note This cast is especially useful when working with quantity points of unknown dimensions
|
||||
* (@c unknown_dimension).
|
||||
*
|
||||
* @tparam ToD a dimension type to use for a target quantity
|
||||
* @tparam ToU a unit type to use for a target quantity
|
||||
*/
|
||||
template<Dimension ToD, Unit ToU, typename D, typename U, typename Rep>
|
||||
requires equivalent<ToD, D> && UnitOf<ToU, ToD>
|
||||
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<D, U, Rep>& q)
|
||||
{
|
||||
return quantity_point_cast<quantity_point<ToD, ToU, Rep>>(q);
|
||||
}
|
||||
|
||||
} // namespace units
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -468,7 +468,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
SECTION("percents")
|
||||
{
|
||||
#if DOWNCAST_MODE == 0
|
||||
const auto q = quantity_cast<dimensionless<percent>>(15._q_m / 100._q_m);
|
||||
const auto q = quantity_cast<dim_one, percent>(15._q_m / 100._q_m);
|
||||
#else
|
||||
const auto q = quantity_cast<percent>(15._q_m / 100._q_m);
|
||||
#endif
|
||||
|
@ -223,6 +223,7 @@ static_assert(quantity_point_cast<length<metre, int>>(quantity_point(1.23_q_m)).
|
||||
static_assert(quantity_point_cast<metre>(quantity_point(2_q_km)).relative().count() == 2000);
|
||||
static_assert(quantity_point_cast<kilometre>(quantity_point(2000_q_m)).relative().count() == 2);
|
||||
static_assert(quantity_point_cast<int>(quantity_point(1.23_q_m)).relative().count() == 1);
|
||||
static_assert(quantity_point_cast<dim_speed, kilometre_per_hour>(quantity_point(2000.0_q_m / 3600.0_q_s)).relative().count() == 2);
|
||||
|
||||
// time
|
||||
|
||||
|
@ -201,7 +201,7 @@ constexpr dimensionless<one> q2 = q1;
|
||||
static_assert(q2.count() == 2000);
|
||||
|
||||
#if DOWNCAST_MODE == 0
|
||||
static_assert(quantity_cast<dimensionless<one>>(q1).count() == 2000);
|
||||
static_assert(quantity_cast<dim_one, one>(q1).count() == 2000);
|
||||
#else
|
||||
static_assert(quantity_cast<one>(q1).count() == 2000);
|
||||
#endif
|
||||
@ -282,6 +282,7 @@ static_assert(quantity_cast<length<metre, int>>(1.23_q_m).count() == 1);
|
||||
static_assert(quantity_cast<metre>(2_q_km).count() == 2000);
|
||||
static_assert(quantity_cast<kilometre>(2000_q_m).count() == 2);
|
||||
static_assert(quantity_cast<int>(1.23_q_m).count() == 1);
|
||||
static_assert(quantity_cast<dim_speed, kilometre_per_hour>(2000.0_q_m / 3600.0_q_s).count() == 2);
|
||||
|
||||
// dimensionless
|
||||
|
||||
@ -313,7 +314,7 @@ static_assert(invalid_dimensionless_operations<int>);
|
||||
static_assert(compare<decltype(10_q_km / 5_q_km), quantity<dim_one, one, std::int64_t>>);
|
||||
|
||||
#if DOWNCAST_MODE == 0
|
||||
static_assert(quantity_cast<dimensionless<percent>>(50._q_m / 100._q_m).count() == 50);
|
||||
static_assert(quantity_cast<dim_one, percent>(50._q_m / 100._q_m).count() == 50);
|
||||
#else
|
||||
static_assert(quantity_cast<percent>(50._q_m / 100._q_m).count() == 50);
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user