diff --git a/src/util/iterutil.hpp b/src/util/iterutil.hpp index 6a9fd159ffe9f75eddf57f2adb5c4d42cb9e7861..a443bf97c733fda54d157bc65fbce61ea46ce039 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 9249800df7125d03a4f589d7a1b5b6adc1e0b676..9e3bd62a620ca40ddad3b3d178be95c4738faef1 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 fb7c7fc7b34128468c1d66891b09267a160b298c..0490928f70e0daffb9400005fcd2b03f37db2943 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);