diff --git a/doc/DESIGN.md b/doc/DESIGN.md index 774c1995..6d2b73bf 100644 --- a/doc/DESIGN.md +++ b/doc/DESIGN.md @@ -377,12 +377,17 @@ public: Additional functions provide the support for operations that result in a different dimension type than those of their arguments. -Another change comparing to `std::chrono::duration` is that the `duration` is using -`std::common_type_t` to find a common representation for a calculation result. Such -a design was reported as problematic by numerics study group members as sometimes we want to provide -a different type in case of multiplication and different in case of division. `std::common_type` lacks -that additional information. That is why `units::quantity` uses the resulting type of a concrete operator -operation and provides it directly to `units::common_quantity_t` type trait. +Beside adding new elements a few other changes where applied compared to the `std::chrono::duration` class: +1. The `duration` is using `std::common_type_t` to find a common representation + for a calculation result. Such a design was reported as problematic by numerics study group members + as sometimes we want to provide a different type in case of multiplication and different in case of + division. `std::common_type` lacks that additional information. That is why `units::quantity` uses + the resulting type of a concrete operator operation and provides it directly to `units::common_quantity_t` + type trait. +2. `operator %` is constrained with `treat_as_floating_point` type trait to limit the types to integral + representations only. Also `operator %(Rep)` takes `Rep` as a template argument to limit implicit + conversions. + #### `quantity_cast` diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index 3c5a803a..e9768e87 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -242,13 +242,16 @@ namespace units { return *this; } - constexpr quantity& operator%=(const rep& rhs) + template + constexpr quantity& operator%=(const Rep2& rhs) + requires (!treat_as_floating_point && !treat_as_floating_point) { value_ %= rhs; return *this; } constexpr quantity& operator%=(const quantity& q) + requires (!treat_as_floating_point) { value_ %= q.count(); return *this; diff --git a/test/unit_test/test_quantity.cpp b/test/unit_test/test_quantity.cpp index 19c99b66..8d580c80 100644 --- a/test/unit_test/test_quantity.cpp +++ b/test/unit_test/test_quantity.cpp @@ -187,6 +187,13 @@ namespace { static_assert((2m /= 2).count() == 1); static_assert((7m %= 2).count() == 1); static_assert((7m %= 2m).count() == 1); +// static_assert((7.m %= 2.).count() == 1); // should not compile +// static_assert((7.m %= 2).count() == 1); // should not compile +// static_assert((7m %= 2.).count() == 1); // should not compile + static_assert((7m %= 2m).count() == 1); +// static_assert((7.m %= 2.m).count() == 1); // should not compile +// static_assert((7.m %= 2m).count() == 1); // should not compile +// static_assert((7m %= 2.m).count() == 1); // should not compile // non-member arithmetic operators