diff options
author | Håvard Pettersen <havardpe@oath.com> | 2020-01-07 11:04:12 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@oath.com> | 2020-01-07 11:04:12 +0000 |
commit | 496a11fb34253292b1496da440742b388c72163b (patch) | |
tree | 3dfb74c9d915eca5f42919fd09db12dde15aa41e | |
parent | 83fccd686c95e881a29eff999e73ca50e8e1f782 (diff) |
added comment and examples
-rw-r--r-- | vespalib/src/tests/visit_ranges/visit_ranges_test.cpp | 21 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/visit_ranges.h | 42 |
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)) { |