mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-31 19:04:27 +02:00
feat: two argument explicit cast support added
This commit is contained in:
@@ -78,16 +78,21 @@ Quantity Cast Overloads
|
|||||||
:linenos:
|
:linenos:
|
||||||
|
|
||||||
std::cout << "Distance: " << quantity_cast<si::length<si::metre, int>>(d) << '\n';
|
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<si::metre>(d) << '\n';
|
||||||
std::cout << "Distance: " << quantity_cast<int>(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
|
`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
|
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:
|
once and leave the rest intact:
|
||||||
|
|
||||||
- line #2 forces only a specific destination unit type,
|
- line #2 forces only a specific destination dimension type,
|
||||||
- line #3 sets only a representation type to the type provided by the user.
|
- 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`
|
`quantity_point_cast` takes anything that works for `quantity_point`
|
||||||
or a specific target `quantity_point`::
|
or a specific target `quantity_point`::
|
||||||
|
@@ -37,7 +37,11 @@ int main()
|
|||||||
using namespace units::physical::si::literals;
|
using namespace units::physical::si::literals;
|
||||||
Speed auto v1 = avg_speed(220_q_km, 2_q_h);
|
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));
|
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);
|
Speed auto v3 = quantity_cast<si::metre_per_second>(v2);
|
||||||
|
#endif
|
||||||
Speed auto v4 = quantity_cast<int>(v3);
|
Speed auto v4 = quantity_cast<int>(v3);
|
||||||
|
|
||||||
std::cout << v1 << '\n'; // 110 km/h
|
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 auto t = si::time<si::second, measurement<double>>(measurement(1.2, 0.1));
|
||||||
|
|
||||||
const Speed auto v1 = a * t;
|
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';
|
std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::kilometre_per_hour>(v1) << '\n';
|
||||||
|
#endif
|
||||||
|
|
||||||
si::length<si::metre, measurement<double>> length(measurement(123., 1.));
|
si::length<si::metre, measurement<double>> length(measurement(123., 1.));
|
||||||
std::cout << "10 * " << length << " = " << 10 * length << '\n';
|
std::cout << "10 * " << length << " = " << 10 * length << '\n';
|
||||||
|
@@ -301,7 +301,7 @@ constexpr ratio cast_ratio(const Q1& from, const Q2& to)
|
|||||||
} // namespace detail
|
} // 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"
|
* 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.
|
* (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"
|
* 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.
|
* (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"
|
* 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.
|
* (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"
|
* 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.
|
* (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"
|
* 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.
|
* (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()));
|
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
|
} // namespace units
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@@ -468,7 +468,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
|||||||
SECTION("percents")
|
SECTION("percents")
|
||||||
{
|
{
|
||||||
#if DOWNCAST_MODE == 0
|
#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
|
#else
|
||||||
const auto q = quantity_cast<percent>(15._q_m / 100._q_m);
|
const auto q = quantity_cast<percent>(15._q_m / 100._q_m);
|
||||||
#endif
|
#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<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<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<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
|
// time
|
||||||
|
|
||||||
|
@@ -201,7 +201,7 @@ constexpr dimensionless<one> q2 = q1;
|
|||||||
static_assert(q2.count() == 2000);
|
static_assert(q2.count() == 2000);
|
||||||
|
|
||||||
#if DOWNCAST_MODE == 0
|
#if DOWNCAST_MODE == 0
|
||||||
static_assert(quantity_cast<dimensionless<one>>(q1).count() == 2000);
|
static_assert(quantity_cast<dim_one, one>(q1).count() == 2000);
|
||||||
#else
|
#else
|
||||||
static_assert(quantity_cast<one>(q1).count() == 2000);
|
static_assert(quantity_cast<one>(q1).count() == 2000);
|
||||||
#endif
|
#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<metre>(2_q_km).count() == 2000);
|
||||||
static_assert(quantity_cast<kilometre>(2000_q_m).count() == 2);
|
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<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
|
// 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>>);
|
static_assert(compare<decltype(10_q_km / 5_q_km), quantity<dim_one, one, std::int64_t>>);
|
||||||
|
|
||||||
#if DOWNCAST_MODE == 0
|
#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
|
#else
|
||||||
static_assert(quantity_cast<percent>(50._q_m / 100._q_m).count() == 50);
|
static_assert(quantity_cast<percent>(50._q_m / 100._q_m).count() == 50);
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user