refactor: integral conversion factor optimized for the case of the same unit type

This commit is contained in:
Mateusz Pusz
2024-06-06 22:19:02 +02:00
parent 3353f492ad
commit 452c6015ed

View File

@ -45,17 +45,22 @@ namespace mp_units {
namespace detail {
template<auto UFrom, auto UTo>
concept IntegralConversionFactor = Unit<decltype(UFrom)> && Unit<decltype(UTo)> &&
decltype(is_integral(decltype(decltype(get_canonical_unit(UFrom))::mag /
decltype(get_canonical_unit(UTo))::mag){}))::value;
template<Unit UFrom, Unit UTo>
[[nodiscard]] consteval bool integral_conversion_factor(UFrom from, UTo to)
{
if constexpr (is_same_v<UFrom, UTo>)
return true;
else
return decltype(is_integral(
decltype(decltype(get_canonical_unit(from))::mag / decltype(get_canonical_unit(to))::mag){}))::value;
}
template<typename QFrom, typename QTo>
concept QuantityConvertibleTo =
Quantity<QFrom> && Quantity<QTo> && implicitly_convertible(QFrom::quantity_spec, QTo::quantity_spec) &&
convertible(QFrom::unit, QTo::unit) &&
(treat_as_floating_point<typename QTo::rep> ||
(!treat_as_floating_point<typename QFrom::rep> && IntegralConversionFactor<QFrom::unit, QTo::unit>)) &&
(!treat_as_floating_point<typename QFrom::rep> && (integral_conversion_factor(QFrom::unit, QTo::unit)))) &&
// TODO consider providing constraints of sudo_cast here rather than testing if it can be called (its return type is
// deduced thus the function is evaluated here and may emit truncating conversion or other warnings)
requires(QFrom q) { detail::sudo_cast<QTo>(q); };