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