aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@oath.com>2020-01-07 11:04:12 +0000
committerHåvard Pettersen <havardpe@oath.com>2020-01-07 11:04:12 +0000
commit496a11fb34253292b1496da440742b388c72163b (patch)
tree3dfb74c9d915eca5f42919fd09db12dde15aa41e
parent83fccd686c95e881a29eff999e73ca50e8e1f782 (diff)
added comment and examples
-rw-r--r--vespalib/src/tests/visit_ranges/visit_ranges_test.cpp21
-rw-r--r--vespalib/src/vespa/vespalib/util/visit_ranges.h42
2 files changed, 63 insertions, 0 deletions
diff --git a/vespalib/src/tests/visit_ranges/visit_ranges_test.cpp b/vespalib/src/tests/visit_ranges/visit_ranges_test.cpp
index d6e83b4d495..cb1ac9bd9c3 100644
--- a/vespalib/src/tests/visit_ranges/visit_ranges_test.cpp
+++ b/vespalib/src/tests/visit_ranges/visit_ranges_test.cpp
@@ -8,6 +8,27 @@
using namespace vespalib;
+TEST(VisitRangeExample, set_intersection) {
+ std::vector<int> first({1,3,7});
+ std::vector<int> second({2,3,8});
+ std::vector<int> result;
+ vespalib::visit_ranges(overload{[](visit_ranges_either, int) {},
+ [&result](visit_ranges_both, int x, int) { result.push_back(x); }},
+ first.begin(), first.end(), second.begin(), second.end());
+ EXPECT_EQ(result, std::vector<int>({3}));
+}
+
+TEST(VisitRangeExample, set_subtraction) {
+ std::vector<int> first({1,3,7});
+ std::vector<int> second({2,3,8});
+ std::vector<int> result;
+ vespalib::visit_ranges(overload{[&result](visit_ranges_first, int a) { result.push_back(a); },
+ [](visit_ranges_second, int) {},
+ [](visit_ranges_both, int, int) {}},
+ first.begin(), first.end(), second.begin(), second.end());
+ EXPECT_EQ(result, std::vector<int>({1,7}));
+}
+
TEST(VisitRangesTest, empty_ranges_can_be_visited) {
std::vector<int> a;
std::vector<int> b;
diff --git a/vespalib/src/vespa/vespalib/util/visit_ranges.h b/vespalib/src/vespa/vespalib/util/visit_ranges.h
index 70e2d9c2da6..9cf1112fe0d 100644
--- a/vespalib/src/vespa/vespalib/util/visit_ranges.h
+++ b/vespalib/src/vespa/vespalib/util/visit_ranges.h
@@ -11,6 +11,48 @@ struct visit_ranges_first : visit_ranges_either {};
struct visit_ranges_second : visit_ranges_either {};
struct visit_ranges_both {};
+/**
+ * Visit elements from two distinct ranges in the order defined by the
+ * given comparator. The comparator must define a strict-weak ordering
+ * across all elements from both ranges and each range must already be
+ * sorted according to the comparator before calling this
+ * function. Pairs of elements from the two ranges (one from each)
+ * that are equal according to the comparator will be visited by a
+ * single callback. The different cases ('from the first range', 'from
+ * the second range' and 'from both ranges') are indicated by using
+ * tagged dispatch in the visitation callback.
+ *
+ * An example treating both inputs equally:
+ * <pre>
+ * TEST(VisitRangeExample, set_intersection) {
+ * std::vector<int> first({1,3,7});
+ * std::vector<int> second({2,3,8});
+ * std::vector<int> result;
+ * vespalib::visit_ranges(overload{[](visit_ranges_either, int) {},
+ * [&result](visit_ranges_both, int x, int) { result.push_back(x); }},
+ * first.begin(), first.end(), second.begin(), second.end());
+ * EXPECT_EQ(result, std::vector<int>({3}));
+ * }
+ * </pre>
+ *
+ * An example treating the inputs differently:
+ * <pre>
+ * TEST(VisitRangeExample, set_subtraction) {
+ * std::vector<int> first({1,3,7});
+ * std::vector<int> second({2,3,8});
+ * std::vector<int> result;
+ * vespalib::visit_ranges(overload{[&result](visit_ranges_first, int a) { result.push_back(a); },
+ * [](visit_ranges_second, int) {},
+ * [](visit_ranges_both, int, int) {}},
+ * first.begin(), first.end(), second.begin(), second.end());
+ * EXPECT_EQ(result, std::vector<int>({1,7}));
+ * }
+ * </pre>
+ *
+ * The intention of this function is to simplify the implementation of
+ * merge-like operations.
+ **/
+
template <typename V, typename ItA, typename ItB, typename Cmp = std::less<> >
void visit_ranges(V &&visitor, ItA pos_a, ItA end_a, ItB pos_b, ItB end_b, Cmp cmp = Cmp()) {
while ((pos_a != end_a) && (pos_b != end_b)) {