feat: from now on truncation is not allowed in compound assignment

This commit is contained in:
Mateusz Pusz
2024-10-30 08:20:54 +01:00
parent d8bc0598fe
commit 8ca8270d2f
4 changed files with 41 additions and 66 deletions
+2 -11
View File
@@ -20,15 +20,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
add_library(unit_tests_static_truncating quantity_test.cpp)
if(NOT ${projectPrefix}API_FREESTANDING)
target_sources(unit_tests_static_truncating PRIVATE chrono_test.cpp)
endif()
target_link_libraries(unit_tests_static_truncating PRIVATE mp-units::mp-units)
target_compile_options(
unit_tests_static_truncating PRIVATE $<IF:$<CXX_COMPILER_ID:MSVC>,/wd4242 /wd4244,-Wno-conversion>
)
add_library(
unit_tests_static
angular_test.cpp
@@ -50,6 +41,7 @@ add_library(
# magnitude_test.cpp
natural_test.cpp
prime_test.cpp
quantity_test.cpp
quantity_point_test.cpp
quantity_spec_test.cpp
ratio_test.cpp
@@ -64,9 +56,8 @@ add_library(
)
if(NOT ${projectPrefix}API_FREESTANDING)
target_sources(unit_tests_static PRIVATE fractional_exponent_quantity.cpp math_test.cpp)
target_sources(unit_tests_static PRIVATE chrono_test.cpp fractional_exponent_quantity.cpp math_test.cpp)
endif()
target_compile_options(unit_tests_static PRIVATE $<$<CXX_COMPILER_ID:GNU>:-Wno-subobject-linkage>)
target_link_libraries(unit_tests_static PRIVATE mp-units::mp-units)
target_link_libraries(unit_tests_static PRIVATE unit_tests_static_truncating)
+8 -24
View File
@@ -465,8 +465,8 @@ static_assert((2.5 * m *= 3 * one).numerical_value_in(m) == 7.5);
static_assert((7.5 * m /= 3 * one).numerical_value_in(m) == 2.5);
// different units
static_assert((1 * m += 1.5 * km).numerical_value_in(m) == 1501);
static_assert((1000 * m -= 0.5 * km).numerical_value_in(m) == 500);
static_assert((1 * m += 1 * km).numerical_value_in(m) == 1001);
static_assert((2000 * m -= 1 * km).numerical_value_in(m) == 1000);
static_assert((3500 * m %= 1 * km).numerical_value_in(m) == 500);
// convertible quantity types
@@ -474,18 +474,6 @@ static_assert((isq::length(1 * m) += isq::height(1 * m)).numerical_value_in(m) =
static_assert((isq::length(2 * m) -= isq::height(1 * m)).numerical_value_in(m) == 1);
static_assert((isq::length(7 * m) %= isq::height(2 * m)).numerical_value_in(m) == 1);
// different representation types with truncation
// clang-format off
static_assert((3 * m += 2.5 * m).numerical_value_in(m) == []{ auto v = 3; v += 2.5; return v; }());
static_assert((3 * m -= 1.5 * m).numerical_value_in(m) == []{ auto v = 3; v -= 1.5; return v; }());
static_assert((2 * m *= 2.5).numerical_value_in(m) == []{ auto v = 2; v *= 2.5; return v; }());
static_assert((10 * m /= 2.5).numerical_value_in(m) == []{ auto v = 10; v /= 2.5; return v; }());
static_assert((2 * m *= 2.5 * one).numerical_value_in(m) == []{ auto v = 2; v *= 2.5; return v; }());
static_assert((10 * m /= 2.5 * one).numerical_value_in(m) == []{ auto v = 10; v /= 2.5; return v; }());
// clang-format on
static_assert((isq::height(3 * m) *= 0.5) == isq::height(1 * m));
// static_assert((std::uint8_t{255} * m %= 256 * m).numerical_value_in(m) == [] {
// std::uint8_t ui(255);
// return ui %= 256;
@@ -495,24 +483,20 @@ static_assert((std::uint8_t{255}* m %= 257 * m).numerical_value_in(m) == [] {
return ui %= 257;
}());
// clang-17 with modules build on ignores disabling conversion warnings
#if !(defined MP_UNITS_COMP_CLANG && MP_UNITS_COMP_CLANG < 18 && defined MP_UNITS_MODULES)
// next two lines trigger conversions warnings
// (warning disabled in CMake for this file)
static_assert((22 * m *= 33.33).numerical_value_in(m) == 733);
static_assert((22 * m /= 3.33).numerical_value_in(m) == 6);
static_assert((22 * m *= 33.33 * one).numerical_value_in(m) == 733);
static_assert((22 * m /= 3.33 * one).numerical_value_in(m) == 6);
#endif
template<template<auto, typename> typename Q>
concept invalid_compound_assignments = requires() {
// truncating not allowed
requires !requires(Q<isq::length[m], int> l) { l += 2.5 * m; };
requires !requires(Q<isq::length[m], int> l) { l -= 2.5 * m; };
requires !requires(Q<isq::length[km], int> l) { l += 2 * isq::length[m]; };
requires !requires(Q<isq::length[km], int> l) { l -= 2 * isq::length[m]; };
requires !requires(Q<isq::length[km], int> l) { l %= 2 * isq::length[m]; };
requires !requires(Q<isq::length[km], int> l) { l %= 2 * percent; };
requires !requires(Q<isq::length[km], int> l) { l %= 2. * percent; };
requires !requires(Q<isq::length[m], int> l) { l *= 2.5; };
requires !requires(Q<isq::length[m], int> l) { l /= 2.5; };
requires !requires(Q<isq::length[m], int> l) { l *= 2.5 * one; };
requires !requires(Q<isq::length[m], int> l) { l /= 2.5 * one; };
// compound assignment with a non-convertible quantity not allowed
requires !requires(Q<isq::height[m], int> l) { l += 2 * isq::length[m]; };