You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ab...@apache.org on 2020/10/13 09:43:29 UTC

[nifi-minifi-cpp] branch main updated: MINIFICPP-1383 intdiv_ceil: disable negative numbers

This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git


The following commit(s) were added to refs/heads/main by this push:
     new 674879f  MINIFICPP-1383 intdiv_ceil: disable negative numbers
674879f is described below

commit 674879ff8319a9167cbe1bf67bc9b1777dbc6557
Author: Marton Szasz <sz...@gmail.com>
AuthorDate: Thu Oct 1 14:35:05 2020 +0200

    MINIFICPP-1383 intdiv_ceil: disable negative numbers
    
    MINIFICPP-1383 check that constexpr division by zero doesn't compile
    
    Signed-off-by: Arpad Boda <ab...@apache.org>
    
    This closes #918
---
 libminifi/include/utils/GeneralUtils.h   |  7 ++---
 libminifi/test/unit/GeneralUtilsTest.cpp | 44 +++++++++++++++++++++++---------
 2 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/libminifi/include/utils/GeneralUtils.h b/libminifi/include/utils/GeneralUtils.h
index 224f455..c132650 100644
--- a/libminifi/include/utils/GeneralUtils.h
+++ b/libminifi/include/utils/GeneralUtils.h
@@ -42,10 +42,11 @@ using std::make_unique;
 #endif /* < C++14 */
 
 template<typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
-T intdiv_ceil(T numerator, T denominator) {
-  gsl_Expects(denominator != 0);
+constexpr T intdiv_ceil(T numerator, T denominator) {
   // note: division and remainder is 1 instruction on x86
-  return numerator / denominator + (numerator % denominator > 0);
+  return gsl_Expects(denominator != 0), ((numerator >= 0) != (denominator > 0)
+      ? numerator / denominator  // negative result rounds towards zero, i.e. up
+      : numerator / denominator + (numerator % denominator != 0));
 }
 
 using gsl::owner;
diff --git a/libminifi/test/unit/GeneralUtilsTest.cpp b/libminifi/test/unit/GeneralUtilsTest.cpp
index f7d12b7..f24b88c 100644
--- a/libminifi/test/unit/GeneralUtilsTest.cpp
+++ b/libminifi/test/unit/GeneralUtilsTest.cpp
@@ -32,18 +32,38 @@ TEST_CASE("GeneralUtils::make_unique", "[make_unique]") {
   REQUIRE("test string" == *pstr);
 }
 
-TEST_CASE("GeneralUtils::intdiv_ceil", "[intdiv_ceil]") {
-  REQUIRE(0 == utils::intdiv_ceil(0, 1));
-  REQUIRE(0 == utils::intdiv_ceil(0, 2));
-  REQUIRE(1 == utils::intdiv_ceil(1, 2));
-  REQUIRE(1 == utils::intdiv_ceil(1, 3));
-  REQUIRE(1 == utils::intdiv_ceil(3, 3));
-  REQUIRE(2 == utils::intdiv_ceil(4, 3));
-  REQUIRE(2 == utils::intdiv_ceil(4, 3));
-  REQUIRE(0 == utils::intdiv_ceil(-1, 3));
-  REQUIRE(-1 == utils::intdiv_ceil(-3, 3));
-  REQUIRE(-1 == utils::intdiv_ceil(-4, 3));
-}
+// intdiv_ceil
+static_assert(0 == utils::intdiv_ceil(0, 1), "");
+static_assert(0 == utils::intdiv_ceil(0, 2), "");
+static_assert(1 == utils::intdiv_ceil(1, 2), "");
+static_assert(1 == utils::intdiv_ceil(1, 3), "");
+static_assert(1 == utils::intdiv_ceil(3, 3), "");
+static_assert(2 == utils::intdiv_ceil(4, 3), "");
+static_assert(2 == utils::intdiv_ceil(5, 3), "");
+static_assert(0 == utils::intdiv_ceil(-1, 3), "");
+static_assert(-1 == utils::intdiv_ceil(-3, 3), "");
+static_assert(-1 == utils::intdiv_ceil(-4, 3), "");
+static_assert(2 == utils::intdiv_ceil(-4, -3), "");
+static_assert(2 == utils::intdiv_ceil(-5, -3), "");
+static_assert(0 == utils::intdiv_ceil(1, -3), "");
+static_assert(-1 == utils::intdiv_ceil(5, -3), "");
+static_assert(3 == utils::intdiv_ceil(6, 2), "");
+static_assert(-3 == utils::intdiv_ceil(-6, 2), "");
+static_assert(-3 == utils::intdiv_ceil(6, -2), "");
+static_assert(3 == utils::intdiv_ceil(-6, -2), "");
+static_assert(0 == utils::intdiv_ceil(0, -10), "");
+
+template<int N, int D, typename = void>
+struct does_compile : std::false_type {};
+
+template<int N, int D>
+struct does_compile<N, D,
+    // we must force evaluation so decltype won't do
+    typename std::enable_if<(utils::intdiv_ceil(N, D), true)>::type> : std::true_type {};
+
+static_assert(does_compile<2, 3>::value, "does_compile should work");
+static_assert(!does_compile<1, 0>::value, "constexpr division by zero shouldn't compile");
+
 
 TEST_CASE("GeneralUtils::exchange", "[exchange]") {
   int a = 1;