Skip to content

Commit 06d7b3a

Browse files
committed
feat: some constraints refactored to throw exceptions with nice error messages
1 parent 47c54ef commit 06d7b3a

File tree

3 files changed

+27
-8
lines changed

3 files changed

+27
-8
lines changed

src/core/include/mp-units/framework/quantity.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <mp-units/bits/hacks.h>
2727
#include <mp-units/bits/module_macros.h>
2828
#include <mp-units/bits/sudo_cast.h>
29+
#include <mp-units/bits/unsatisfied.h>
2930
#include <mp-units/compat_macros.h>
3031
#include <mp-units/framework/customization_points.h>
3132
#include <mp-units/framework/dimension_concepts.h>
@@ -76,16 +77,21 @@ template<typename T, typename Arg>
7677
concept ValuePreservingAssignment = std::assignable_from<T&, Arg> && is_value_preserving<std::remove_cvref_t<Arg>, T>;
7778

7879
template<auto FromUnit, auto ToUnit, typename Rep>
79-
concept ValuePreservingScaling1Rep = SaneScaling<FromUnit, ToUnit, Rep> &&
80-
(treat_as_floating_point<Rep> || (integral_conversion_factor(FromUnit, ToUnit)));
80+
concept ValuePreservingScaling1Rep =
81+
SaneScaling<FromUnit, ToUnit, Rep> &&
82+
(treat_as_floating_point<Rep> || (integral_conversion_factor(FromUnit, ToUnit)) ||
83+
unsatisfied<"Scaling from '{}' to '{}' is not value-preserving for '{}' representation type">(
84+
unit_symbol(FromUnit), unit_symbol(ToUnit), type_name<Rep>()));
8185

8286
template<auto FromUnit, typename FromRep, auto ToUnit, typename ToRep>
8387
concept ValuePreservingScaling2Reps =
8488
// TODO consider providing constraints of sudo_cast to check if representation types can be scaled between each other
8589
// CastableReps<FromRep, ToRep, FromUnit, ToUnit> &&
8690
SaneScaling<FromUnit, ToUnit, ToRep> &&
8791
(treat_as_floating_point<ToRep> ||
88-
(!treat_as_floating_point<FromRep> && integral_conversion_factor(FromUnit, ToUnit)));
92+
(!treat_as_floating_point<FromRep> && integral_conversion_factor(FromUnit, ToUnit)) ||
93+
unsatisfied<"Scaling from '{}' as '{}' to '{}' as '{}' is not value-preserving">(
94+
unit_symbol(FromUnit), type_name<FromRep>(), unit_symbol(ToUnit), type_name<ToRep>()));
8995

9096
template<typename QTo, typename QFrom>
9197
concept QuantityConstructibleFrom =

src/core/include/mp-units/framework/unit_concepts.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
// IWYU pragma: private, include <mp-units/framework.h>
2626
#include <mp-units/bits/module_macros.h>
27+
#include <mp-units/bits/unsatisfied.h>
2728
#include <mp-units/framework/quantity_spec_concepts.h>
2829
#include <mp-units/framework/symbolic_expression.h>
2930
#include <mp-units/framework/unit_magnitude.h>
@@ -97,8 +98,11 @@ concept AssociatedUnit = Unit<U> && detail::has_associated_quantity(U{});
9798
* the provided @c QS value.
9899
*/
99100
MP_UNITS_EXPORT template<typename U, auto QS>
100-
concept UnitOf = AssociatedUnit<U> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> &&
101-
(implicitly_convertible(get_quantity_spec(U{}), QS));
101+
concept UnitOf =
102+
AssociatedUnit<U> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> &&
103+
(implicitly_convertible(get_quantity_spec(U{}), QS) ||
104+
(unsatisfied<"Unit '{}' is associated with quantity of kind '{}' which is not convertible to the '{}' quantity">(
105+
U{}, type_name(get_quantity_spec(U{})._quantity_spec_), type_name(QS))));
102106

103107
namespace detail {
104108

@@ -107,10 +111,17 @@ concept WeakUnitOf =
107111
Unit<U> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> && ((!AssociatedUnit<U>) || UnitOf<U, QS>);
108112

109113
template<auto U1, auto U2>
110-
concept UnitsOfCompatibleQuantities = explicitly_convertible(get_quantity_spec(U1), get_quantity_spec(U2));
114+
concept UnitsOfCompatibleQuantities =
115+
explicitly_convertible(get_quantity_spec(U1), get_quantity_spec(U2)) ||
116+
unsatisfied<"'{}' and '{}' units are of quantities of incompatible kinds ('{}' and '{}')">(
117+
U1, U2, type_name(get_quantity_spec(U1)._quantity_spec_), type_name(get_quantity_spec(U2)._quantity_spec_));
111118

112119
template<auto U1, auto U2>
113-
concept ConvertibleUnits = (get_canonical_unit(U1).reference_unit == get_canonical_unit(U2).reference_unit);
120+
concept ConvertibleUnits = (get_canonical_unit(U1).reference_unit == get_canonical_unit(U2).reference_unit) ||
121+
unsatisfied<
122+
"Units '{}' and '{}' are not convertible because they are defined in terms of "
123+
"different reference units ('{}' and '{}')">(U1, U2, get_canonical_unit(U1).reference_unit,
124+
get_canonical_unit(U2).reference_unit);
114125

115126
template<typename U1, auto U2>
116127
concept UnitConvertibleTo =

src/core/include/mp-units/framework/value_cast.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ template<typename Rep, Unit UFrom, Unit UTo>
5858

5959
template<auto FromU, auto ToU, typename Rep>
6060
concept SaneScaling = UnitConvertibleTo<MP_UNITS_REMOVE_CONST(decltype(FromU)), ToU> &&
61-
(!detail::scaling_overflows_non_zero_values<Rep>(FromU, ToU));
61+
((!detail::scaling_overflows_non_zero_values<Rep>(FromU, ToU)) ||
62+
unsatisfied<"The result of scaling '{}' to '{}' overflows the '{}' representation type">(
63+
FromU, ToU, type_name<Rep>()));
6264

6365
} // namespace detail
6466

0 commit comments

Comments
 (0)