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);