diff --git a/src/core/include/mp-units/framework/quantity.h b/src/core/include/mp-units/framework/quantity.h index 211d2239..c44be919 100644 --- a/src/core/include/mp-units/framework/quantity.h +++ b/src/core/include/mp-units/framework/quantity.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -76,8 +77,11 @@ template concept ValuePreservingAssignment = std::assignable_from && is_value_preserving, T>; template -concept ValuePreservingScaling1Rep = SaneScaling && - (treat_as_floating_point || (integral_conversion_factor(FromUnit, ToUnit))); +concept ValuePreservingScaling1Rep = + SaneScaling && + (treat_as_floating_point || (integral_conversion_factor(FromUnit, ToUnit)) || + unsatisfied<"Scaling from '{}' to '{}' is not value-preserving for '{}' representation type">( + unit_symbol(FromUnit), unit_symbol(ToUnit), type_name())); template concept ValuePreservingScaling2Reps = @@ -85,7 +89,9 @@ concept ValuePreservingScaling2Reps = // CastableReps && SaneScaling && (treat_as_floating_point || - (!treat_as_floating_point && integral_conversion_factor(FromUnit, ToUnit))); + (!treat_as_floating_point && integral_conversion_factor(FromUnit, ToUnit)) || + unsatisfied<"Scaling from '{}' as '{}' to '{}' as '{}' is not value-preserving">( + unit_symbol(FromUnit), type_name(), unit_symbol(ToUnit), type_name())); template concept QuantityConstructibleFrom = diff --git a/src/core/include/mp-units/framework/unit_concepts.h b/src/core/include/mp-units/framework/unit_concepts.h index 060728f4..61d92e3f 100644 --- a/src/core/include/mp-units/framework/unit_concepts.h +++ b/src/core/include/mp-units/framework/unit_concepts.h @@ -24,6 +24,7 @@ // IWYU pragma: private, include #include +#include #include #include #include @@ -97,8 +98,11 @@ concept AssociatedUnit = Unit && detail::has_associated_quantity(U{}); * the provided @c QS value. */ MP_UNITS_EXPORT template -concept UnitOf = AssociatedUnit && QuantitySpec && - (implicitly_convertible(get_quantity_spec(U{}), QS)); +concept UnitOf = + AssociatedUnit && QuantitySpec && + (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 && QuantitySpec && ((!AssociatedUnit) || UnitOf); template -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 -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 concept UnitConvertibleTo = diff --git a/src/core/include/mp-units/framework/value_cast.h b/src/core/include/mp-units/framework/value_cast.h index 01814f7a..34b28f3e 100644 --- a/src/core/include/mp-units/framework/value_cast.h +++ b/src/core/include/mp-units/framework/value_cast.h @@ -58,7 +58,9 @@ template template concept SaneScaling = UnitConvertibleTo && - (!detail::scaling_overflows_non_zero_values(FromU, ToU)); + ((!detail::scaling_overflows_non_zero_values(FromU, ToU)) || + unsatisfied<"The result of scaling '{}' to '{}' overflows the '{}' representation type">( + FromU, ToU, type_name())); } // namespace detail