From ebaaaf5ea74a405b2553f2b17ebed077ef4e4836 Mon Sep 17 00:00:00 2001 From: Yaraslau Tamashevich Date: Fri, 21 Jun 2024 19:35:29 +0300 Subject: [PATCH] Add division check for debug mode --- CMakeLists.txt | 3 +++ include/boxed-cpp/boxed.hpp | 42 +++++++++++++++++++++++++++++++++++-- test-boxed-cpp.cpp | 26 +++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b834525..b6b849a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,9 @@ target_include_directories(boxed-cpp INTERFACE $ $ ) +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + target_compile_definitions(boxed-cpp INTERFACE BOXED_DEBUG) +endif() # Generate the version, config and target files include(CMakePackageConfigHelpers) diff --git a/include/boxed-cpp/boxed.hpp b/include/boxed-cpp/boxed.hpp index 3986c8b..579b5f0 100644 --- a/include/boxed-cpp/boxed.hpp +++ b/include/boxed-cpp/boxed.hpp @@ -4,7 +4,11 @@ #include #include #include +#include #include +#if defined(BOXED_DEBUG) + #include +#endif namespace boxed { @@ -126,7 +130,41 @@ template constexpr boxed& operator/=(boxed& template constexpr boxed& operator%=(boxed& a, boxed const& b) noexcept { a.value %= b.value; return a; } template std::ostream& operator<<(std::ostream& os, boxed const& v) { return os << v.value; } - // clang-format on + +// clang-format on +#if defined(BOXED_DEBUG) + + template + constexpr boxed operator/(boxed const& a, boxed const& b) + { + auto div = std::div(b.value, a.value); + if (div.rem != 0) + throw std::invalid_argument("Division is not exact"); + return boxed { div.quot }; + } + + template + constexpr boxed operator/(boxed const& a, T b) + { + return a / boxed { b }; + } + + template + constexpr boxed operator/(T b, boxed const& a) + { + return boxed { b } / a; + } + + template + constexpr boxed& operator/=(boxed& a, boxed const& b) + { + auto res = a / b; + a = res; + return a; + } + +#endif + } // namespace detail namespace helper @@ -216,7 +254,7 @@ namespace fmt { template -struct fmt::formatter> +struct formatter> { constexpr auto parse(fmt::format_parse_context& ctx) { return ctx.begin(); } diff --git a/test-boxed-cpp.cpp b/test-boxed-cpp.cpp index dcf107a..23ea128 100644 --- a/test-boxed-cpp.cpp +++ b/test-boxed-cpp.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -215,3 +216,28 @@ TEST_CASE("advanced") REQUIRE(x_coord(rho, theta, phi) == x_coord(theta, phi, rho)); REQUIRE(x_coord(phi, theta, rho) == x_coord(phi, theta, rho)); } + +TEST_CASE("devision of integral_types") +{ + using Int = boxed::boxed; + int int_a { 10 }; + Int Int_a { 10 }; + int int_b { 3 }; + Int Int_b { 3 }; +#if defined(BOXED_DEBUG) + REQUIRE_THROWS_AS(int_a / Int_b, std::invalid_argument); + REQUIRE_THROWS_AS(Int_a / int_b, std::invalid_argument); + REQUIRE_THROWS_AS(Int_a / Int_b, std::invalid_argument); + REQUIRE_THROWS_AS([&](){ + Int_a /= Int_b; + }(), std::invalid_argument); + + +#else + REQUIRE(unbox(int_a / Int_b) == 3); + REQUIRE(unbox(Int_a / int_b) == 3); + REQUIRE(unbox(Int_a / Int_b) == 3); + Int_a /= Int_b; + REQUIRE(unbox(Int_a) == 3); +#endif +}