feat: some constraints refactored to throw exceptions with nice error messages

This commit is contained in:
Mateusz Pusz
2025-06-20 13:38:17 +02:00
parent 47c54ef4c9
commit 06d7b3a560
3 changed files with 27 additions and 8 deletions

View File

@ -26,6 +26,7 @@
#include <mp-units/bits/hacks.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/bits/sudo_cast.h>
#include <mp-units/bits/unsatisfied.h>
#include <mp-units/compat_macros.h>
#include <mp-units/framework/customization_points.h>
#include <mp-units/framework/dimension_concepts.h>
@ -76,8 +77,11 @@ template<typename T, typename Arg>
concept ValuePreservingAssignment = std::assignable_from<T&, Arg> && is_value_preserving<std::remove_cvref_t<Arg>, T>;
template<auto FromUnit, auto ToUnit, typename Rep>
concept ValuePreservingScaling1Rep = SaneScaling<FromUnit, ToUnit, Rep> &&
(treat_as_floating_point<Rep> || (integral_conversion_factor(FromUnit, ToUnit)));
concept ValuePreservingScaling1Rep =
SaneScaling<FromUnit, ToUnit, Rep> &&
(treat_as_floating_point<Rep> || (integral_conversion_factor(FromUnit, ToUnit)) ||
unsatisfied<"Scaling from '{}' to '{}' is not value-preserving for '{}' representation type">(
unit_symbol(FromUnit), unit_symbol(ToUnit), type_name<Rep>()));
template<auto FromUnit, typename FromRep, auto ToUnit, typename ToRep>
concept ValuePreservingScaling2Reps =
@ -85,7 +89,9 @@ concept ValuePreservingScaling2Reps =
// CastableReps<FromRep, ToRep, FromUnit, ToUnit> &&
SaneScaling<FromUnit, ToUnit, ToRep> &&
(treat_as_floating_point<ToRep> ||
(!treat_as_floating_point<FromRep> && integral_conversion_factor(FromUnit, ToUnit)));
(!treat_as_floating_point<FromRep> && integral_conversion_factor(FromUnit, ToUnit)) ||
unsatisfied<"Scaling from '{}' as '{}' to '{}' as '{}' is not value-preserving">(
unit_symbol(FromUnit), type_name<FromRep>(), unit_symbol(ToUnit), type_name<ToRep>()));
template<typename QTo, typename QFrom>
concept QuantityConstructibleFrom =

View File

@ -24,6 +24,7 @@
// IWYU pragma: private, include <mp-units/framework.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/bits/unsatisfied.h>
#include <mp-units/framework/quantity_spec_concepts.h>
#include <mp-units/framework/symbolic_expression.h>
#include <mp-units/framework/unit_magnitude.h>
@ -97,8 +98,11 @@ concept AssociatedUnit = Unit<U> && detail::has_associated_quantity(U{});
* the provided @c QS value.
*/
MP_UNITS_EXPORT template<typename U, auto QS>
concept UnitOf = AssociatedUnit<U> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> &&
(implicitly_convertible(get_quantity_spec(U{}), QS));
concept UnitOf =
AssociatedUnit<U> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> &&
(implicitly_convertible(get_quantity_spec(U{}), QS) ||
(unsatisfied<"Unit '{}' is associated with quantity of kind '{}' which is not convertible to the '{}' quantity">(
U{}, type_name(get_quantity_spec(U{})._quantity_spec_), type_name(QS))));
namespace detail {
@ -107,10 +111,17 @@ concept WeakUnitOf =
Unit<U> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> && ((!AssociatedUnit<U>) || UnitOf<U, QS>);
template<auto U1, auto U2>
concept UnitsOfCompatibleQuantities = explicitly_convertible(get_quantity_spec(U1), get_quantity_spec(U2));
concept UnitsOfCompatibleQuantities =
explicitly_convertible(get_quantity_spec(U1), get_quantity_spec(U2)) ||
unsatisfied<"'{}' and '{}' units are of quantities of incompatible kinds ('{}' and '{}')">(
U1, U2, type_name(get_quantity_spec(U1)._quantity_spec_), type_name(get_quantity_spec(U2)._quantity_spec_));
template<auto U1, auto U2>
concept ConvertibleUnits = (get_canonical_unit(U1).reference_unit == get_canonical_unit(U2).reference_unit);
concept ConvertibleUnits = (get_canonical_unit(U1).reference_unit == get_canonical_unit(U2).reference_unit) ||
unsatisfied<
"Units '{}' and '{}' are not convertible because they are defined in terms of "
"different reference units ('{}' and '{}')">(U1, U2, get_canonical_unit(U1).reference_unit,
get_canonical_unit(U2).reference_unit);
template<typename U1, auto U2>
concept UnitConvertibleTo =

View File

@ -58,7 +58,9 @@ template<typename Rep, Unit UFrom, Unit UTo>
template<auto FromU, auto ToU, typename Rep>
concept SaneScaling = UnitConvertibleTo<MP_UNITS_REMOVE_CONST(decltype(FromU)), ToU> &&
(!detail::scaling_overflows_non_zero_values<Rep>(FromU, ToU));
((!detail::scaling_overflows_non_zero_values<Rep>(FromU, ToU)) ||
unsatisfied<"The result of scaling '{}' to '{}' overflows the '{}' representation type">(
FromU, ToU, type_name<Rep>()));
} // namespace detail