From 320fd2fd395ca8d944d4594feecea3723995ab1e Mon Sep 17 00:00:00 2001 From: Kevin Backhouse Date: Thu, 27 Oct 2022 11:09:25 +0100 Subject: [PATCH 1/3] Use std::is_signed and std::enable_if. --- src/safe_op.hpp | 45 +++++++------------------------------- unitTests/test_safe_op.cpp | 34 ++++++++++++++-------------- 2 files changed, 25 insertions(+), 54 deletions(-) diff --git a/src/safe_op.hpp b/src/safe_op.hpp index 27f542afe4..da602b0c38 100644 --- a/src/safe_op.hpp +++ b/src/safe_op.hpp @@ -5,6 +5,7 @@ #include #include +#include #ifdef _MSC_VER #include @@ -37,35 +38,6 @@ namespace Safe { * is available. */ namespace Internal { -/*! - * @brief Helper struct to determine whether a type is signed or unsigned - * - * This struct is a backport of std::is_signed from C++11. It has a public - * enum with the property VALUE which is true when the type is signed or - * false if it is unsigned. - */ -template -struct is_signed { - enum { VALUE = static_cast(-1) < static_cast(0) }; -}; - -/*! - * @brief Helper struct for SFINAE, from C++11 - - * This struct has a public typedef called type typedef'd to T if B is - * true. Otherwise there is no typedef. - */ -template -struct enable_if {}; - -/*! - * @brief Specialization of enable_if for the case B == true - */ -template -struct enable_if { - using type = T; -}; - /*! * @brief Check the addition of two numbers for overflows for signed * integer types larger than int or with the same size as int. @@ -84,9 +56,8 @@ struct enable_if { * https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow */ template -typename enable_if::VALUE && sizeof(T) >= sizeof(int), bool>::type fallback_add_overflow(T summand_1, - T summand_2, - T& result) { +typename std::enable_if::value && sizeof(T) >= sizeof(int), bool>::type fallback_add_overflow( + T summand_1, T summand_2, T& result) { if (((summand_2 >= 0) && (summand_1 > std::numeric_limits::max() - summand_2)) || ((summand_2 < 0) && (summand_1 < std::numeric_limits::min() - summand_2))) { return true; @@ -116,9 +87,8 @@ typename enable_if::VALUE && sizeof(T) >= sizeof(int), bool>::type * https://wiki.sei.cmu.edu/confluence/display/c/INT02-C.+Understand+integer+conversion+rules */ template -typename enable_if::VALUE && sizeof(T) < sizeof(int), bool>::type fallback_add_overflow(T summand_1, - T summand_2, - T& result) { +typename std::enable_if::value && sizeof(T) < sizeof(int), bool>::type fallback_add_overflow( + T summand_1, T summand_2, T& result) { const int res = summand_1 + summand_2; if ((res > std::numeric_limits::max()) || (res < std::numeric_limits::min())) { return true; @@ -145,7 +115,8 @@ typename enable_if::VALUE && sizeof(T) < sizeof(int), bool>::type f * https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */ template -typename enable_if::VALUE, bool>::type fallback_add_overflow(T summand_1, T summand_2, T& result) { +typename std::enable_if::value, bool>::type fallback_add_overflow(T summand_1, T summand_2, + T& result) { result = summand_1 + summand_2; return result < summand_1; } @@ -255,7 +226,7 @@ T add(T summand_1, T summand_2) { * when `num == std::numeric_limits::min()`. */ template -typename Internal::enable_if::VALUE, T>::type abs(T num) throw() { +typename std::enable_if::value, T>::type abs(T num) throw() { if (num == std::numeric_limits::min()) { return std::numeric_limits::max(); } diff --git a/unitTests/test_safe_op.cpp b/unitTests/test_safe_op.cpp index e0037e1bc8..438f26914d 100644 --- a/unitTests/test_safe_op.cpp +++ b/unitTests/test_safe_op.cpp @@ -26,42 +26,42 @@ struct AdditionTestValues; * Overload for unsigned types. */ template -struct AdditionTestValues::VALUE>::type> { +struct AdditionTestValues::VALUE>::type> { static const size_t case_count = 5; static const T summand[case_count]; static const bool overflow[case_count][case_count]; }; template -const T AdditionTestValues::VALUE>::type>::summand[] = { +const T AdditionTestValues::VALUE>::type>::summand[] = { 0, 1, 2, static_cast(std::numeric_limits::max() - 1), std::numeric_limits::max()}; template -const bool - AdditionTestValues::VALUE>::type>::overflow[case_count][case_count] = { - // 0 - {false, false, false, false, false}, - // 1 - {false, false, false, false, true}, - // 2 - {false, false, false, true, true}, - // max - 1 - {false, false, true, true, true}, - // max - {false, true, true, true, true}}; +const bool AdditionTestValues< + T, typename std::enable_if::VALUE>::type>::overflow[case_count][case_count] = { + // 0 + {false, false, false, false, false}, + // 1 + {false, false, false, false, true}, + // 2 + {false, false, false, true, true}, + // max - 1 + {false, false, true, true, true}, + // max + {false, true, true, true, true}}; /*! * Overload for signed integers */ template -struct AdditionTestValues::VALUE>::type> { +struct AdditionTestValues::VALUE>::type> { static const size_t case_count = 8; static const T summand[case_count]; static const bool overflow[case_count][case_count]; }; template -const T AdditionTestValues::VALUE>::type>::summand[] = { +const T AdditionTestValues::VALUE>::type>::summand[] = { std::numeric_limits::min(), static_cast(std::numeric_limits::min() + 1), -1, @@ -73,7 +73,7 @@ const T AdditionTestValues::VALUE>::t template const bool - AdditionTestValues::VALUE>::type>::overflow[case_count][case_count] = { + AdditionTestValues::VALUE>::type>::overflow[case_count][case_count] = { // min {true, true, true, false, false, false, false, false}, // min + 1 From 0de1340f75a10b8ee65212e254bf66bcf77734f9 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 27 Oct 2022 22:36:06 +0100 Subject: [PATCH 2/3] Use std::enable_if_t and std::is_signed_v. --- unitTests/test_safe_op.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/unitTests/test_safe_op.cpp b/unitTests/test_safe_op.cpp index 438f26914d..29284158ee 100644 --- a/unitTests/test_safe_op.cpp +++ b/unitTests/test_safe_op.cpp @@ -26,19 +26,19 @@ struct AdditionTestValues; * Overload for unsigned types. */ template -struct AdditionTestValues::VALUE>::type> { +struct AdditionTestValues>> { static const size_t case_count = 5; static const T summand[case_count]; static const bool overflow[case_count][case_count]; }; template -const T AdditionTestValues::VALUE>::type>::summand[] = { +const T AdditionTestValues>>::summand[] = { 0, 1, 2, static_cast(std::numeric_limits::max() - 1), std::numeric_limits::max()}; template const bool AdditionTestValues< - T, typename std::enable_if::VALUE>::type>::overflow[case_count][case_count] = { + T, std::enable_if_t>>::overflow[case_count][case_count] = { // 0 {false, false, false, false, false}, // 1 @@ -54,14 +54,14 @@ const bool AdditionTestValues< * Overload for signed integers */ template -struct AdditionTestValues::VALUE>::type> { +struct AdditionTestValues>> { static const size_t case_count = 8; static const T summand[case_count]; static const bool overflow[case_count][case_count]; }; template -const T AdditionTestValues::VALUE>::type>::summand[] = { +const T AdditionTestValues>>::summand[] = { std::numeric_limits::min(), static_cast(std::numeric_limits::min() + 1), -1, @@ -73,7 +73,7 @@ const T AdditionTestValues::VALUE>: template const bool - AdditionTestValues::VALUE>::type>::overflow[case_count][case_count] = { + AdditionTestValues>>::overflow[case_count][case_count] = { // min {true, true, true, false, false, false, false, false}, // min + 1 From d6df99e6a2ace29fb9888d0d8464b0167fa5acad Mon Sep 17 00:00:00 2001 From: Kevin Backhouse Date: Thu, 27 Oct 2022 22:59:04 +0100 Subject: [PATCH 3/3] clang-format --- unitTests/test_safe_op.cpp | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/unitTests/test_safe_op.cpp b/unitTests/test_safe_op.cpp index 29284158ee..714915420a 100644 --- a/unitTests/test_safe_op.cpp +++ b/unitTests/test_safe_op.cpp @@ -37,8 +37,7 @@ const T AdditionTestValues>>::summand[] 0, 1, 2, static_cast(std::numeric_limits::max() - 1), std::numeric_limits::max()}; template -const bool AdditionTestValues< - T, std::enable_if_t>>::overflow[case_count][case_count] = { +const bool AdditionTestValues>>::overflow[case_count][case_count] = { // 0 {false, false, false, false, false}, // 1 @@ -72,24 +71,23 @@ const T AdditionTestValues>>::summand[] std::numeric_limits::max()}; template -const bool - AdditionTestValues>>::overflow[case_count][case_count] = { - // min - {true, true, true, false, false, false, false, false}, - // min + 1 - {true, true, false, false, false, false, false, false}, - // -1 - {true, false, false, false, false, false, false, false}, - // 0 - {false, false, false, false, false, false, false, false}, - // 1 - {false, false, false, false, false, false, false, true}, - // 2 - {false, false, false, false, false, false, true, true}, - // max - 1 - {false, false, false, false, false, true, true, true}, - // max - {false, false, false, false, true, true, true, true}}; +const bool AdditionTestValues>>::overflow[case_count][case_count] = { + // min + {true, true, true, false, false, false, false, false}, + // min + 1 + {true, true, false, false, false, false, false, false}, + // -1 + {true, false, false, false, false, false, false, false}, + // 0 + {false, false, false, false, false, false, false, false}, + // 1 + {false, false, false, false, false, false, false, true}, + // 2 + {false, false, false, false, false, false, true, true}, + // max - 1 + {false, false, false, false, false, true, true, true}, + // max + {false, false, false, false, true, true, true, true}}; /*! * Test the addition of all combinations of AdditionTestValues::summand[i],