From 8005cadabed0689137ff38822b76f29429345bc3 Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis <karakasis@cscs.ch> Date: Wed, 31 Aug 2016 10:39:16 +0200 Subject: [PATCH] Custom distance() function. This new `util:distance()` operating on an iterator `I` and a sentinel `S`. It reverts to `std::distance()` if `I==S`, otherwise it increments iterator sequentially until it reaches the sentinel and returns the number of total increments. Also removed tests for ranges with `l>r`. --- src/util/iterutil.hpp | 21 +++++++++++++++++++++ src/util/range.hpp | 8 ++++---- tests/unit/test_range.cpp | 24 ++++++++++++++---------- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/util/iterutil.hpp b/src/util/iterutil.hpp index 6a9fd159..a443bf97 100644 --- a/src/util/iterutil.hpp +++ b/src/util/iterutil.hpp @@ -43,6 +43,27 @@ upto(I iter, E end) { return iter==I{end}? iter: I{std::prev(end)}; } + +template <typename I, typename E> +enable_if_t<std::is_same<I, E>::value && is_forward_iterator<I>::value, + typename std::iterator_traits<I>::difference_type> +distance(I first, E last) { + return std::distance(first, last); +} + +template <typename I, typename E> +enable_if_t<!std::is_same<I, E>::value && is_forward_iterator<I>::value, + typename std::iterator_traits<I>::difference_type> +distance(I first, E last) { + typename std::iterator_traits<I>::difference_type ret = 0; + while (first != last) { + ++first; + ++ret; + } + + return ret; +} + /* * Provide a proxy object for operator->() for iterator adaptors that * present rvalues on dereference. diff --git a/src/util/range.hpp b/src/util/range.hpp index 9249800d..9e3bd62a 100644 --- a/src/util/range.hpp +++ b/src/util/range.hpp @@ -78,12 +78,12 @@ struct range { template <typename V = iterator> enable_if_t<is_forward_iterator<V>::value, size_type> size() const { - auto b = make_sentinel_iterator(begin(), end()); - auto e = make_sentinel_end(begin(), end()); - return std::distance(b, e); + return util::distance(begin(), end()); } - constexpr size_type max_size() const { return std::numeric_limits<size_type>::max(); } + constexpr size_type max_size() const { + return std::numeric_limits<size_type>::max(); + } void swap(range& other) { std::swap(left, other.left); diff --git a/tests/unit/test_range.cpp b/tests/unit/test_range.cpp index fb7c7fc7..0490928f 100644 --- a/tests/unit/test_range.cpp +++ b/tests/unit/test_range.cpp @@ -77,15 +77,18 @@ TEST(range, empty) { auto l = 2; auto r = 5; - auto empty_range = util::make_range(&xs[l], &xs[l]); - EXPECT_TRUE(empty_range.empty()); - EXPECT_TRUE(empty_range.size() == 0); - - - EXPECT_TRUE(util::make_range(&xs[l], &xs[l]).empty()); - EXPECT_TRUE(util::make_range(&xs[r], &xs[r]).empty()); - EXPECT_TRUE(util::make_range(&xs[r], &xs[l]).empty()); - EXPECT_EQ(0u, util::make_range(&xs[r], &xs[l]).size()); + auto empty_range_ll = util::make_range(&xs[l], &xs[l]); + EXPECT_TRUE(empty_range_ll.empty()); + EXPECT_EQ(empty_range_ll.begin() == empty_range_ll.end(), + empty_range_ll.empty()); + EXPECT_EQ(0u, empty_range_ll.size()); + + + auto empty_range_rr = util::make_range(&xs[r], &xs[r]); + EXPECT_TRUE(empty_range_rr.empty()); + EXPECT_EQ(empty_range_rr.begin() == empty_range_rr.end(), + empty_range_rr.empty()); + EXPECT_EQ(0u, empty_range_rr.size()); } TEST(range, input_iterator) { @@ -133,6 +136,7 @@ TEST(range, sentinel) { } EXPECT_EQ(s, std::string(cstr)); + EXPECT_EQ(s.size(), cstr_range.size()); s.clear(); for (auto c: canonical_view(cstr_range)) { @@ -144,6 +148,7 @@ TEST(range, sentinel) { const char *empty_cstr = ""; auto empty_cstr_range = util::make_range(empty_cstr, null_terminated); EXPECT_TRUE(empty_cstr_range.empty()); + EXPECT_EQ(0u, empty_cstr_range.size()); } template <typename V> @@ -221,7 +226,6 @@ TYPED_TEST_P(counter_range, iteration) { } } - REGISTER_TYPED_TEST_CASE_P(counter_range, max_size, extreme_size, size, at, iteration); -- GitLab