diff --git a/src/util/iterutil.hpp b/src/util/iterutil.hpp
index a443bf97c733fda54d157bc65fbce61ea46ce039..a357b667b488a8796520e70a6e84901f61e65033 100644
--- a/src/util/iterutil.hpp
+++ b/src/util/iterutil.hpp
@@ -43,16 +43,19 @@ 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>
+template <typename I, typename E,
+          typename C = typename common_random_access_iterator<I,E>::type>
+enable_if_t<std::is_same<I, E>::value ||
+            (has_common_random_access_iterator<I,E>::value &&
+             is_forward_iterator<I>::value),
+            typename std::iterator_traits<C>::difference_type>
 distance(I first, E last) {
-    return std::distance(first, last);
+    return std::distance(static_cast<C>(first), static_cast<C>(last));
 }
 
 template <typename I, typename E>
-enable_if_t<!std::is_same<I, E>::value && is_forward_iterator<I>::value,
+enable_if_t<!has_common_random_access_iterator<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;
diff --git a/src/util/meta.hpp b/src/util/meta.hpp
index 40f08d481f23199e8e06a47fc41acdd58fdab8c9..e45d31604d08b53dea1a722cd329c241ffa4da36 100644
--- a/src/util/meta.hpp
+++ b/src/util/meta.hpp
@@ -151,6 +151,36 @@ struct is_forward_iterator<T, enable_if_t<
 template <typename T>
 using is_forward_iterator_t = typename is_forward_iterator<T>::type;
 
+
+template <typename I, typename E, typename = void, typename = void>
+struct common_random_access_iterator {};
+
+template <typename I, typename E>
+struct common_random_access_iterator<
+    I,
+    E,
+    void_t<decltype(false ? std::declval<I>() : std::declval<E>())>,
+    enable_if_t<
+        is_random_access_iterator<
+            decay_t<decltype(false ? std::declval<I>() : std::declval<E>())>
+        >::value
+    >
+> {
+    using type = decay_t<
+        decltype(false ? std::declval<I>() : std::declval<E>())
+    >;
+};
+
+template <typename I, typename E, typename = void>
+struct has_common_random_access_iterator: public std::false_type {};
+
+template <typename I, typename E>
+struct has_common_random_access_iterator<
+    I, E, void_t<typename common_random_access_iterator<I, E>::type>
+> : public std::true_type {};
+
+
+
 } // namespace util
 } // namespace mc
 } // namespace nest
diff --git a/tests/unit/test_range.cpp b/tests/unit/test_range.cpp
index 0490928f70e0daffb9400005fcd2b03f37db2943..5b1d84cb97dd72f0dd0cad36afdc27bc389437a8 100644
--- a/tests/unit/test_range.cpp
+++ b/tests/unit/test_range.cpp
@@ -12,6 +12,7 @@
 #endif
 
 #include <util/counter.hpp>
+#include <util/meta.hpp>
 #include <util/range.hpp>
 #include <util/sentinel.hpp>
 
@@ -20,7 +21,7 @@ using namespace nest::mc;
 TEST(range, list_iterator) {
     std::list<int> l = { 2, 4, 6, 8, 10 };
 
-    auto s = util::make_range(l.begin(), l.end());
+    auto s  = util::make_range(l.begin(), l.end());
 
     EXPECT_EQ(s.left, l.begin());
     EXPECT_EQ(s.right, l.end());
@@ -42,6 +43,10 @@ TEST(range, list_iterator) {
 
     auto sum2 = std::accumulate(s.begin(), s.end(), 0);
     EXPECT_EQ(check, sum2);
+
+    // Check that different begin/end iterators are treated correctly
+    auto sc = util::make_range(l.begin(), l.cend());
+    EXPECT_EQ(l.size(), sc.size());
 }
 
 TEST(range, pointer) {
@@ -77,24 +82,54 @@ TEST(range, empty) {
     auto l = 2;
     auto r = 5;
 
-    auto empty_range_ll = util::make_range(&xs[l], &xs[l]);
+    auto empty_range_ll = util::make_range((const int *) &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]);
+    auto empty_range_rr = util::make_range(&xs[r], (const int *) &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());
 }
 
+template<typename I, typename E, typename = void>
+struct util_distance_enabled : public std::false_type {};
+
+// This is the same test for enabling util::distance
+template<typename I, typename E>
+struct util_distance_enabled<
+    I, E, util::void_t<
+              util::enable_if_t<
+                  !util::has_common_random_access_iterator<I, E>::value &&
+                  util::is_forward_iterator<I>::value
+    >>> : public std::true_type {};
+
+TEST(range, size) {
+    static_assert(util_distance_enabled<
+                  typename std::list<int>::iterator,
+                  typename std::list<int>::const_iterator>::value,
+                  "util::distance not enabled");
+    static_assert(!util_distance_enabled<
+                  typename std::vector<int>::const_iterator,
+                  typename std::vector<int>::iterator>::value,
+                  "util::distance erroneously enabled");
+    static_assert(!util_distance_enabled<int*, int*>::value,
+                  "util::distance erroneously enabled");
+    static_assert(!util_distance_enabled<int*, const int*>::value,
+                  "util::distance erroneously enabled");
+    static_assert(!util_distance_enabled<const int*, int*>::value,
+                  "util::distance erroneously enabled");
+}
+
 TEST(range, input_iterator) {
     int nums[] = { 10, 9, 8, 7, 6 };
     std::istringstream sin("10 9 8 7 6");
-    auto s = util::make_range(std::istream_iterator<int>(sin), std::istream_iterator<int>());
+    auto s = util::make_range(std::istream_iterator<int>(sin),
+                              std::istream_iterator<int>());
 
     EXPECT_TRUE(std::equal(s.begin(), s.end(), &nums[0]));
 }