You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by al...@apache.org on 2022/11/08 00:42:51 UTC

[datasketches-cpp] 01/01: operator->

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

alsay pushed a commit to branch operator_arrow
in repository https://gitbox.apache.org/repos/asf/datasketches-cpp.git

commit ef69ebaef08ab6ecbf553da13e8482ffeee1afd2
Author: AlexanderSaydakov <Al...@users.noreply.github.com>
AuthorDate: Mon Nov 7 16:42:44 2022 -0800

    operator->
---
 common/include/common_defs.hpp              | 10 ++++
 common/include/quantiles_sorted_view.hpp    | 16 ++----
 common/test/quantiles_sorted_view_test.cpp  |  4 ++
 kll/include/kll_sketch.hpp                  |  4 +-
 kll/include/kll_sketch_impl.hpp             | 87 +++++++++++++++--------------
 kll/test/kll_sketch_test.cpp                | 17 ++++--
 quantiles/include/quantiles_sketch.hpp      |  4 +-
 quantiles/include/quantiles_sketch_impl.hpp | 10 +++-
 quantiles/test/quantiles_sketch_test.cpp    | 25 +++++----
 req/include/req_sketch.hpp                  |  4 +-
 req/include/req_sketch_impl.hpp             |  9 ++-
 req/test/req_sketch_test.cpp                | 13 +++--
 12 files changed, 123 insertions(+), 80 deletions(-)

diff --git a/common/include/common_defs.hpp b/common/include/common_defs.hpp
index a1ab6cf..7437536 100644
--- a/common/include/common_defs.hpp
+++ b/common/include/common_defs.hpp
@@ -86,6 +86,16 @@ static inline void write(std::ostream& os, const T* ptr, size_t size_bytes) {
   os.write(reinterpret_cast<const char*>(ptr), size_bytes);
 }
 
+// wrapper for iterators to implement operator-> returning temporary value
+template<typename T>
+class return_value_holder {
+public:
+  return_value_holder(T value): value_(value) {}
+  const T* operator->() const { return std::addressof(value_); }
+private:
+  T value_;
+};
+
 } // namespace
 
 #endif // _COMMON_DEFS_HPP_
diff --git a/common/include/quantiles_sorted_view.hpp b/common/include/quantiles_sorted_view.hpp
index fffee87..e965cb1 100755
--- a/common/include/quantiles_sorted_view.hpp
+++ b/common/include/quantiles_sorted_view.hpp
@@ -23,6 +23,8 @@
 #include <functional>
 #include <cmath>
 
+#include "common_defs.hpp"
+
 namespace datasketches {
 
 template<
@@ -123,24 +125,16 @@ public:
   const_iterator(const Base& it, const Base& begin): Base(it), begin(begin) {}
 
   template<typename TT = T, typename std::enable_if<std::is_arithmetic<TT>::value, int>::type = 0>
-  value_type operator*() const { return Base::operator*(); }
+  const value_type operator*() const { return Base::operator*(); }
 
   template<typename TT = T, typename std::enable_if<!std::is_arithmetic<TT>::value, int>::type = 0>
-  value_type operator*() const { return value_type(*(Base::operator*().first), Base::operator*().second); }
-
-  class return_value_holder {
-  public:
-    return_value_holder(value_type value): value_(value) {}
-    const value_type* operator->() const { return &value_; }
-  private:
-    value_type value_;
-  };
+  const value_type operator*() const { return value_type(*(Base::operator*().first), Base::operator*().second); }
 
   template<typename TT = T, typename std::enable_if<std::is_arithmetic<TT>::value, int>::type = 0>
   const value_type* operator->() const { return Base::operator->(); }
 
   template<typename TT = T, typename std::enable_if<!std::is_arithmetic<TT>::value, int>::type = 0>
-  return_value_holder operator->() const { return **this; }
+  const return_value_holder<value_type> operator->() const { return **this; }
 
   uint64_t get_weight() const {
     if (*this == begin) return Base::operator*().second;
diff --git a/common/test/quantiles_sorted_view_test.cpp b/common/test/quantiles_sorted_view_test.cpp
index a9ecfbd..609408d 100644
--- a/common/test/quantiles_sorted_view_test.cpp
+++ b/common/test/quantiles_sorted_view_test.cpp
@@ -45,8 +45,12 @@ TEST_CASE("set 0", "sorted view") {
     REQUIRE(view.size() == 1);
 
     auto it = view.begin();
+    // using operator->
     REQUIRE(it->first == 10);
     REQUIRE(it->second == 1);
+    // using operator*
+    REQUIRE((*it).first == 10);
+    REQUIRE((*it).second == 1);
     REQUIRE(it.get_weight() == 1);
     REQUIRE(it.get_cumulative_weight() == 1);
     REQUIRE(it.get_cumulative_weight(false) == 0);
diff --git a/kll/include/kll_sketch.hpp b/kll/include/kll_sketch.hpp
index d0cadc8..3407afc 100644
--- a/kll/include/kll_sketch.hpp
+++ b/kll/include/kll_sketch.hpp
@@ -588,12 +588,14 @@ class kll_sketch {
 template<typename T, typename C, typename A>
 class kll_sketch<T, C, A>::const_iterator: public std::iterator<std::input_iterator_tag, T> {
 public:
+  using value_type = std::pair<const T&, const uint64_t>;
   friend class kll_sketch<T, C, A>;
   const_iterator& operator++();
   const_iterator& operator++(int);
   bool operator==(const const_iterator& other) const;
   bool operator!=(const const_iterator& other) const;
-  const std::pair<const T&, const uint64_t> operator*() const;
+  const value_type operator*() const;
+  const return_value_holder<value_type> operator->() const;
 private:
   const T* items;
   const uint32_t* levels;
diff --git a/kll/include/kll_sketch_impl.hpp b/kll/include/kll_sketch_impl.hpp
index 894d7b2..933640b 100644
--- a/kll/include/kll_sketch_impl.hpp
+++ b/kll/include/kll_sketch_impl.hpp
@@ -1019,47 +1019,6 @@ typename kll_sketch<T, C, A>::const_iterator kll_sketch<T, C, A>::end() const {
   return kll_sketch<T, C, A>::const_iterator(nullptr, levels_.data(), num_levels_);
 }
 
-// kll_sketch::const_iterator implementation
-
-template<typename T, typename C, typename A>
-kll_sketch<T, C, A>::const_iterator::const_iterator(const T* items, const uint32_t* levels, const uint8_t num_levels):
-items(items), levels(levels), num_levels(num_levels), index(items == nullptr ? levels[num_levels] : levels[0]), level(items == nullptr ? num_levels : 0), weight(1)
-{}
-
-template<typename T, typename C, typename A>
-typename kll_sketch<T, C, A>::const_iterator& kll_sketch<T, C, A>::const_iterator::operator++() {
-  ++index;
-  if (index == levels[level + 1]) { // go to the next non-empty level
-    do {
-      ++level;
-      weight *= 2;
-    } while (level < num_levels && levels[level] == levels[level + 1]);
-  }
-  return *this;
-}
-
-template<typename T, typename C, typename A>
-typename kll_sketch<T, C, A>::const_iterator& kll_sketch<T, C, A>::const_iterator::operator++(int) {
-  const_iterator tmp(*this);
-  operator++();
-  return tmp;
-}
-
-template<typename T, typename C, typename A>
-bool kll_sketch<T, C, A>::const_iterator::operator==(const const_iterator& other) const {
-  return index == other.index;
-}
-
-template<typename T, typename C, typename A>
-bool kll_sketch<T, C, A>::const_iterator::operator!=(const const_iterator& other) const {
-  return !operator==(other);
-}
-
-template<typename T, typename C, typename A>
-const std::pair<const T&, const uint64_t> kll_sketch<T, C, A>::const_iterator::operator*() const {
-  return std::pair<const T&, const uint64_t>(items[index], weight);
-}
-
 template<typename T, typename C, typename A>
 class kll_sketch<T, C, A>::item_deleter {
   public:
@@ -1109,6 +1068,52 @@ void kll_sketch<T, C, A>::reset_sorted_view() {
   }
 }
 
+// kll_sketch::const_iterator implementation
+
+template<typename T, typename C, typename A>
+kll_sketch<T, C, A>::const_iterator::const_iterator(const T* items, const uint32_t* levels, const uint8_t num_levels):
+items(items), levels(levels), num_levels(num_levels), index(items == nullptr ? levels[num_levels] : levels[0]), level(items == nullptr ? num_levels : 0), weight(1)
+{}
+
+template<typename T, typename C, typename A>
+typename kll_sketch<T, C, A>::const_iterator& kll_sketch<T, C, A>::const_iterator::operator++() {
+  ++index;
+  if (index == levels[level + 1]) { // go to the next non-empty level
+    do {
+      ++level;
+      weight *= 2;
+    } while (level < num_levels && levels[level] == levels[level + 1]);
+  }
+  return *this;
+}
+
+template<typename T, typename C, typename A>
+typename kll_sketch<T, C, A>::const_iterator& kll_sketch<T, C, A>::const_iterator::operator++(int) {
+  const_iterator tmp(*this);
+  operator++();
+  return tmp;
+}
+
+template<typename T, typename C, typename A>
+bool kll_sketch<T, C, A>::const_iterator::operator==(const const_iterator& other) const {
+  return index == other.index;
+}
+
+template<typename T, typename C, typename A>
+bool kll_sketch<T, C, A>::const_iterator::operator!=(const const_iterator& other) const {
+  return !operator==(other);
+}
+
+template<typename T, typename C, typename A>
+auto kll_sketch<T, C, A>::const_iterator::operator*() const -> const value_type {
+  return value_type(items[index], weight);
+}
+
+template<typename T, typename C, typename A>
+auto kll_sketch<T, C, A>::const_iterator::operator->() const -> const return_value_holder<value_type> {
+  return **this;
+}
+
 } /* namespace datasketches */
 
 #endif
diff --git a/kll/test/kll_sketch_test.cpp b/kll/test/kll_sketch_test.cpp
index 48b64e9..7ce92c9 100644
--- a/kll/test/kll_sketch_test.cpp
+++ b/kll/test/kll_sketch_test.cpp
@@ -73,8 +73,8 @@ TEST_CASE("kll sketch", "[kll_sketch]") {
     REQUIRE_THROWS_AS(sketch.get_PMF(split_points, 1), std::runtime_error);
     REQUIRE_THROWS_AS(sketch.get_CDF(split_points, 1), std::runtime_error);
 
-    for (auto it: sketch) {
-      (void) it; // to suppress "unused" warning
+    for (auto pair: sketch) {
+      unused(pair); // to suppress "unused" warning
       FAIL("should be no iterations over an empty sketch");
     }
   }
@@ -107,11 +107,16 @@ TEST_CASE("kll sketch", "[kll_sketch]") {
     REQUIRE(quantiles[2] == 1.0);
 
     int count = 0;
-    for (auto it: sketch) {
-      REQUIRE(it.second == 1);
+    for (auto pair: sketch) {
+      REQUIRE(pair.second == 1);
       ++count;
     }
     REQUIRE(count == 1);
+
+    // iterator dereferencing
+    auto it = sketch.begin();
+    REQUIRE(it->first == 1.0f);
+    REQUIRE((*it).first == 1.0f);
   }
 
   SECTION("NaN") {
@@ -211,9 +216,9 @@ TEST_CASE("kll sketch", "[kll_sketch]") {
 
     uint32_t count = 0;
     uint64_t total_weight = 0;
-    for (auto it: sketch) {
+    for (auto pair: sketch) {
       ++count;
-      total_weight += it.second;
+      total_weight += pair.second;
     }
     REQUIRE(count == sketch.get_num_retained());
     REQUIRE(total_weight == sketch.get_n());
diff --git a/quantiles/include/quantiles_sketch.hpp b/quantiles/include/quantiles_sketch.hpp
index da80766..184b784 100644
--- a/quantiles/include/quantiles_sketch.hpp
+++ b/quantiles/include/quantiles_sketch.hpp
@@ -582,11 +582,13 @@ private:
 template<typename T, typename C, typename A>
 class quantiles_sketch<T, C, A>::const_iterator: public std::iterator<std::input_iterator_tag, T> {
 public:
+  using value_type = std::pair<const T&, const uint64_t>;
   const_iterator& operator++();
   const_iterator& operator++(int);
   bool operator==(const const_iterator& other) const;
   bool operator!=(const const_iterator& other) const;
-  std::pair<const T&, const uint64_t> operator*() const;
+  const value_type operator*() const;
+  const return_value_holder<value_type> operator->() const;
 private:
   friend class quantiles_sketch<T, C, A>;
   using Level = std::vector<T, A>;
diff --git a/quantiles/include/quantiles_sketch_impl.hpp b/quantiles/include/quantiles_sketch_impl.hpp
index d0d972f..bb90005 100644
--- a/quantiles/include/quantiles_sketch_impl.hpp
+++ b/quantiles/include/quantiles_sketch_impl.hpp
@@ -26,7 +26,6 @@
 #include <iomanip>
 #include <sstream>
 
-#include "common_defs.hpp"
 #include "count_zeros.hpp"
 #include "conditional_forward.hpp"
 
@@ -1355,8 +1354,13 @@ bool quantiles_sketch<T, C, A>::const_iterator::operator!=(const const_iterator&
 }
 
 template<typename T, typename C, typename A>
-std::pair<const T&, const uint64_t> quantiles_sketch<T, C, A>::const_iterator::operator*() const {
-  return std::pair<const T&, const uint64_t>(level_ == -1 ? base_buffer_[index_] : levels_[level_][index_], weight_);
+auto quantiles_sketch<T, C, A>::const_iterator::operator*() const -> const value_type {
+  return value_type(level_ == -1 ? base_buffer_[index_] : levels_[level_][index_], weight_);
+}
+
+template<typename T, typename C, typename A>
+auto quantiles_sketch<T, C, A>::const_iterator::operator->() const -> const return_value_holder<value_type> {
+  return **this;
 }
 
 } /* namespace datasketches */
diff --git a/quantiles/test/quantiles_sketch_test.cpp b/quantiles/test/quantiles_sketch_test.cpp
index 3e3a884..3e47c33 100644
--- a/quantiles/test/quantiles_sketch_test.cpp
+++ b/quantiles/test/quantiles_sketch_test.cpp
@@ -71,11 +71,11 @@ TEST_CASE("quantiles sketch", "[quantiles_sketch]") {
     REQUIRE_THROWS_AS(sketch.get_PMF(split_points, 1), std::runtime_error);
     REQUIRE_THROWS_AS(sketch.get_CDF(split_points, 1), std::runtime_error);
 
-    for (auto it: sketch) {
-      unused(it);
+    for (auto pair: sketch) {
+      unused(pair);
       FAIL("should be no iterations over an empty sketch");
     }
-  }
+}
 
   SECTION("get bad quantile") {
     quantiles_float_sketch sketch(64, std::less<float>(), 0);
@@ -106,12 +106,17 @@ TEST_CASE("quantiles sketch", "[quantiles_sketch]") {
     REQUIRE(quantiles[2] == 1.0);
 
     int count = 0;
-    for (auto it: sketch) {
-      REQUIRE(it.second == 1);
+    for (auto pair: sketch) {
+      REQUIRE(pair.second == 1);
       ++count;
     }
     REQUIRE(count == 1);
-  }
+
+    // iterator dereferencing
+    auto it = sketch.begin();
+    REQUIRE(it->first == 1.0f);
+    REQUIRE((*it).first == 1.0f);
+}
 
   SECTION("NaN") {
     quantiles_float_sketch sketch(256, std::less<float>(), 0);
@@ -163,8 +168,8 @@ TEST_CASE("quantiles sketch", "[quantiles_sketch]") {
     REQUIRE(quantiles[2] == quantiles2[2]);
 
     int count = 0;
-    for (auto it: sketch) {
-      REQUIRE(it.second == 1);
+    for (auto pair: sketch) {
+      REQUIRE(pair.second == 1);
       ++count;
     }
     REQUIRE(count == n);
@@ -228,9 +233,9 @@ TEST_CASE("quantiles sketch", "[quantiles_sketch]") {
 
     uint32_t count = 0;
     uint64_t total_weight = 0;
-    for (auto it: sketch) {
+    for (auto pair: sketch) {
       ++count;
-      total_weight += it.second;
+      total_weight += pair.second;
     }
     REQUIRE(count == sketch.get_num_retained());
     REQUIRE(total_weight == sketch.get_n());
diff --git a/req/include/req_sketch.hpp b/req/include/req_sketch.hpp
index f033b6a..b6375c5 100755
--- a/req/include/req_sketch.hpp
+++ b/req/include/req_sketch.hpp
@@ -401,11 +401,13 @@ private:
 template<typename T, typename C, typename A>
 class req_sketch<T, C, A>::const_iterator: public std::iterator<std::input_iterator_tag, T> {
 public:
+  using value_type = std::pair<const T&, const uint64_t>;
   const_iterator& operator++();
   const_iterator& operator++(int);
   bool operator==(const const_iterator& other) const;
   bool operator!=(const const_iterator& other) const;
-  std::pair<const T&, const uint64_t> operator*() const;
+  const value_type operator*() const;
+  const return_value_holder<value_type> operator->() const;
 private:
   using LevelsIterator = typename std::vector<Compactor, AllocCompactor>::const_iterator;
   LevelsIterator levels_it_;
diff --git a/req/include/req_sketch_impl.hpp b/req/include/req_sketch_impl.hpp
index 62aed71..7634a80 100755
--- a/req/include/req_sketch_impl.hpp
+++ b/req/include/req_sketch_impl.hpp
@@ -848,8 +848,13 @@ bool req_sketch<T, C, A>::const_iterator::operator!=(const const_iterator& other
 }
 
 template<typename T, typename C, typename A>
-std::pair<const T&, const uint64_t> req_sketch<T, C, A>::const_iterator::operator*() const {
-  return std::pair<const T&, const uint64_t>(*compactor_it_, 1ULL << (*levels_it_).get_lg_weight());
+auto req_sketch<T, C, A>::const_iterator::operator*() const -> const value_type {
+  return value_type(*compactor_it_, 1ULL << (*levels_it_).get_lg_weight());
+}
+
+template<typename T, typename C, typename A>
+auto req_sketch<T, C, A>::const_iterator::operator->() const -> const return_value_holder<value_type> {
+  return **this;
 }
 
 } /* namespace datasketches */
diff --git a/req/test/req_sketch_test.cpp b/req/test/req_sketch_test.cpp
index 9515962..9a8daa1 100755
--- a/req/test/req_sketch_test.cpp
+++ b/req/test/req_sketch_test.cpp
@@ -79,11 +79,16 @@ TEST_CASE("req sketch: single value, lra", "[req_sketch]") {
   REQUIRE(quantiles[2] == 1);
 
   unsigned count = 0;
-  for (auto it: sketch) {
-    REQUIRE(it.second == 1);
+  for (auto pair: sketch) {
+    REQUIRE(pair.second == 1);
     ++count;
   }
   REQUIRE(count == 1);
+
+  // iterator dereferencing
+  auto it = sketch.begin();
+  REQUIRE(it->first == 1.0f);
+  REQUIRE((*it).first == 1.0f);
 }
 
 TEST_CASE("req sketch: repeated values", "[req_sketch]") {
@@ -182,8 +187,8 @@ TEST_CASE("req sketch: estimation mode", "[req_sketch]") {
   REQUIRE(sketch.get_rank_upper_bound(0.5, 1) > 0.5);
 
   unsigned count = 0;
-  for (auto it: sketch) {
-    REQUIRE(it.second >= 1);
+  for (auto pair: sketch) {
+    REQUIRE(pair.second >= 1);
     ++count;
   }
   REQUIRE(count == sketch.get_num_retained());


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org