Skip to content

Commit 52e0033

Browse files
committed
Add division check for debug mode
1 parent 82b3621 commit 52e0033

File tree

4 files changed

+74
-6
lines changed

4 files changed

+74
-6
lines changed

.github/workflows/build.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@ on:
1111
jobs:
1212
check_clang_format:
1313
name: "Check C++ style"
14-
runs-on: ubuntu-22.04
14+
runs-on: ubuntu-24.04
1515
steps:
1616
- uses: actions/checkout@v3
1717
- name: Install clang
1818
run: |
1919
wget https://apt.llvm.org/llvm.sh
2020
chmod +x llvm.sh
21-
sudo ./llvm.sh 17
22-
sudo apt-get install clang-format-17
21+
sudo ./llvm.sh 18
22+
sudo apt-get install clang-format-18
2323
- name: "Clang-format"
24-
run: clang-format-17 --Werror --dry-run test-boxed-cpp.cpp include/boxed-cpp/boxed.hpp
24+
run: clang-format-18 --Werror --dry-run test-boxed-cpp.cpp include/boxed-cpp/boxed.hpp
2525

2626
editorconfig:
2727
name: "Check editorconfig"
@@ -37,7 +37,7 @@ jobs:
3737
matrix:
3838
os: [ubuntu-24.04, ubuntu-22.04]
3939
cxx: [20]
40-
build_type: ["RelWithDebInfo"]
40+
build_type: ["RelWithDebInfo", "Debug"]
4141
llvm_version:
4242
[
4343
"17",

CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ target_include_directories(boxed-cpp INTERFACE
2020
$<BUILD_INTERFACE:${${PROJECT_NAME}_SOURCE_DIR}/include>
2121
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
2222
)
23+
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
24+
target_compile_definitions(boxed-cpp INTERFACE BOXED_DEBUG)
25+
endif()
2326

2427
# Generate the version, config and target files
2528
include(CMakePackageConfigHelpers)

include/boxed-cpp/boxed.hpp

+39-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
#include <compare>
55
#include <iostream>
66
#include <limits>
7+
#include <stdexcept>
78
#include <type_traits>
9+
#if defined(BOXED_DEBUG)
10+
#include <cassert>
11+
#endif
812

913
namespace boxed
1014
{
@@ -126,7 +130,41 @@ template <typename T, typename U> constexpr boxed<T, U>& operator/=(boxed<T, U>&
126130
template <typename T, typename U> constexpr boxed<T, U>& operator%=(boxed<T, U>& a, boxed<T, U> const& b) noexcept { a.value %= b.value; return a; }
127131

128132
template <typename T, typename U> std::ostream& operator<<(std::ostream& os, boxed<T, U> const& v) { return os << v.value; }
129-
// clang-format on
133+
134+
// clang-format on
135+
#if defined(BOXED_DEBUG)
136+
137+
template <std::integral T, typename U>
138+
constexpr boxed<T, U> operator/(boxed<T, U> const& a, boxed<T, U> const& b)
139+
{
140+
auto div = std::div(b.value, a.value);
141+
if (div.rem != 0)
142+
throw std::invalid_argument("Division is not exact");
143+
return boxed<T, U> { div.quot };
144+
}
145+
146+
template <std::integral T, typename U>
147+
constexpr boxed<T, U> operator/(boxed<T, U> const& a, T b)
148+
{
149+
return a / boxed<T, U> { b };
150+
}
151+
152+
template <std::integral T, typename U>
153+
constexpr boxed<T, U> operator/(T b, boxed<T, U> const& a)
154+
{
155+
return boxed<T, U> { b } / a;
156+
}
157+
158+
template <std::integral T, typename U>
159+
constexpr boxed<T, U>& operator/=(boxed<T, U>& a, boxed<T, U> const& b)
160+
{
161+
auto res = a / b;
162+
a = res;
163+
return a;
164+
}
165+
166+
#endif
167+
130168
} // namespace detail
131169

132170
namespace helper

test-boxed-cpp.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <cmath>
55
#include <functional>
66
#include <limits>
7+
#include <stdexcept>
78
#include <type_traits>
89

910
#include <boxed-cpp/boxed.hpp>
@@ -216,6 +217,32 @@ TEST_CASE("advanced")
216217
REQUIRE(x_coord(phi, theta, rho) == x_coord(phi, theta, rho));
217218
}
218219

220+
TEST_CASE("devision of integral_types")
221+
{
222+
using Int = boxed::boxed<int>;
223+
int int_a { 10 };
224+
Int Int_a { 10 };
225+
int int_b { 3 };
226+
Int Int_b { 3 };
227+
#if defined(BOXED_DEBUG)
228+
REQUIRE_THROWS_AS(int_a / Int_b, std::invalid_argument);
229+
REQUIRE_THROWS_AS(Int_a / int_b, std::invalid_argument);
230+
REQUIRE_THROWS_AS(Int_a / Int_b, std::invalid_argument);
231+
REQUIRE_THROWS_AS(
232+
[&]() {
233+
Int_a /= Int_b;
234+
}(),
235+
std::invalid_argument);
236+
237+
#else
238+
REQUIRE(unbox(int_a / Int_b) == 3);
239+
REQUIRE(unbox(Int_a / int_b) == 3);
240+
REQUIRE(unbox(Int_a / Int_b) == 3);
241+
Int_a /= Int_b;
242+
REQUIRE(unbox(Int_a) == 3);
243+
#endif
244+
}
245+
219246
#ifdef __has_include
220247
#if __has_include(<version>)
221248
#include <version>

0 commit comments

Comments
 (0)