[libcxx-commits] [libcxx] b476039 - [libc++] Refactor the tests for ranges::{advance, next, prev}

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jan 13 10:57:59 PST 2022


Author: Louis Dionne
Date: 2022-01-13T13:57:55-05:00
New Revision: b476039e8b90dd67da7928c64637ba363e7e8b8e

URL: https://github.com/llvm/llvm-project/commit/b476039e8b90dd67da7928c64637ba363e7e8b8e
DIFF: https://github.com/llvm/llvm-project/commit/b476039e8b90dd67da7928c64637ba363e7e8b8e.diff

LOG: [libc++] Refactor the tests for ranges::{advance,next,prev}

This makes all the tests consistent and improves code coverage. This also
uncovers a bug with negative indices in advance() (which also impacts
prev()) -- I'll fix that in a subsequent patch.

I chose to only count operations in the tests for ranges::advance because
doing so in prev() and next() too was reaching diminishing returns, and
didn't meaningfully improve our test coverage.

Added: 
    

Modified: 
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count.pass.cpp
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator.pass.cpp
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_count.pass.cpp
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_count_sentinel.pass.cpp
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_sentinel.pass.cpp
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator.pass.cpp
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator_count.pass.cpp
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator_count_sentinel.pass.cpp
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/types.h

Removed: 
    


################################################################################
diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count.pass.cpp
index 4a76f0716345..f8da9e7c1e0d 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count.pass.cpp
@@ -13,67 +13,58 @@
 
 #include <iterator>
 
-#include <array>
 #include <cassert>
 
 #include "test_iterators.h"
+#include "test_macros.h"
 
-using range_t = std::array<int, 10>;
+template <bool Count, typename It>
+constexpr void check(int* first, std::iter_
diff erence_t<It> n, int* expected) {
+  using Difference = std::iter_
diff erence_t<It>;
+  Difference const M = (expected - first); // expected travel distance (which may be negative)
+  auto abs = [](auto x) { return x < 0 ? -x : x; };
 
-template <std::input_or_output_iterator It>
-constexpr void check_move_forward(std::ptr
diff _t const n) {
-  auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-  auto first = stride_counting_iterator(It(range.begin()));
-  std::ranges::advance(first, n);
-
-  assert(first.base().base() == range.begin() + n);
-  if constexpr (std::random_access_iterator<It>) {
-    assert(first.stride_count() == 0 || first.stride_count() == 1);
-    assert(first.stride_displacement() == 1);
-  } else {
-    assert(first.stride_count() == n);
-    assert(first.stride_displacement() == n);
+  {
+    It it(first);
+    std::ranges::advance(it, n);
+    assert(base(it) == expected);
+    ASSERT_SAME_TYPE(decltype(std::ranges::advance(it, n)), void);
   }
-}
-
-template <std::bidirectional_iterator It>
-constexpr void check_move_backward(std::ptr
diff _t const n) {
-  auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-  auto first = stride_counting_iterator(It(range.begin() + n));
-  std::ranges::advance(first, -n);
-  assert(first.base().base() == range.begin());
 
-  if constexpr (std::random_access_iterator<It>) {
-    assert(first.stride_count() == 0 || first.stride_count() == 1);
-    assert(first.stride_displacement() == 1);
-  } else {
-    assert(first.stride_count() == n);
-    assert(first.stride_displacement() == -n);
+  // Count operations
+  if constexpr (Count) {
+    auto it = stride_counting_iterator(It(first));
+    std::ranges::advance(it, n);
+    if constexpr (std::random_access_iterator<It>) {
+      assert(it.stride_count() <= 1);
+    } else {
+      assert(it.stride_count() == abs(M));
+    }
   }
 }
 
 constexpr bool test() {
-  check_move_forward<cpp17_input_iterator<range_t::const_iterator> >(1);
-  check_move_forward<cpp20_input_iterator<range_t::const_iterator> >(2);
-  check_move_forward<forward_iterator<range_t::const_iterator> >(3);
-  check_move_forward<bidirectional_iterator<range_t::const_iterator> >(4);
-  check_move_forward<random_access_iterator<range_t::const_iterator> >(5);
-  check_move_forward<contiguous_iterator<range_t::const_iterator> >(6);
-  check_move_forward<output_iterator<range_t::iterator> >(7);
+  int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
 
-  check_move_backward<bidirectional_iterator<range_t::const_iterator> >(4);
-  check_move_backward<random_access_iterator<range_t::const_iterator> >(5);
-  check_move_backward<contiguous_iterator<range_t::const_iterator> >(6);
+  // Check advancing forward
+  for (int n = 0; n != 10; ++n) {
+    check<false, cpp17_input_iterator<int*>>(  range, n, range+n);
+    check<false, cpp20_input_iterator<int*>>(  range, n, range+n);
+    check<true,  forward_iterator<int*>>(      range, n, range+n);
+    check<true,  bidirectional_iterator<int*>>(range, n, range+n);
+    check<true,  random_access_iterator<int*>>(range, n, range+n);
+    check<true,  contiguous_iterator<int*>>(   range, n, range+n);
+    check<true,  int*>(                        range, n, range+n);
+    check<true,  output_iterator<int*> >(      range, n, range+n);
+  }
 
-  // Zero should be checked for each case and each overload
-  check_move_forward<cpp17_input_iterator<range_t::const_iterator> >(0);
-  check_move_forward<cpp20_input_iterator<range_t::const_iterator> >(0);
-  check_move_forward<forward_iterator<range_t::const_iterator> >(0);
-  check_move_forward<bidirectional_iterator<range_t::const_iterator> >(0);
-  check_move_forward<random_access_iterator<range_t::const_iterator> >(0);
-  check_move_forward<output_iterator<range_t::iterator> >(0);
-  check_move_backward<bidirectional_iterator<range_t::const_iterator> >(0);
-  check_move_backward<random_access_iterator<range_t::const_iterator> >(0);
+  // Check advancing backward
+  for (int n = 0; n != 10; ++n) {
+    check<true,  bidirectional_iterator<int*>>(range+9, -n, range+9 - n);
+    check<true,  random_access_iterator<int*>>(range+9, -n, range+9 - n);
+    check<true,  contiguous_iterator<int*>>(   range+9, -n, range+9 - n);
+    check<true,  int*>(                        range+9, -n, range+9 - n);
+  }
 
   return true;
 }

diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp
index a3fa81374098..104e912e3c35 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp
@@ -13,68 +13,90 @@
 
 #include <iterator>
 
-#include <array>
 #include <cassert>
 #include <climits>
+#include <concepts>
+#include <cstddef>
 
 #include "test_iterators.h"
 #include "../types.h"
 
-using range_t = std::array<int, 10>;
+template <bool Count, typename It>
+constexpr void check_forward(int* first, int* last, std::iter_
diff erence_t<It> n, int* expected) {
+  using Difference = std::iter_
diff erence_t<It>;
+  Difference const M = (expected - first); // expected travel distance
 
-struct expected_t {
-  range_t::const_iterator coordinate;
-  std::ptr
diff _t result;
-};
+  {
+    It it(first);
+    auto sent = sentinel_wrapper(It(last));
+    std::same_as<Difference> auto result = std::ranges::advance(it, n, sent);
+    assert(result == n - M);
+    assert(base(it) == expected);
+  }
 
-template <std::input_or_output_iterator It>
-constexpr void check_forward_sized_sentinel(std::ptr
diff _t n, expected_t expected, range_t& range) {
-  using Difference = std::iter_
diff erence_t<It>;
-  auto current = stride_counting_iterator(It(range.begin()));
-  Difference const result = std::ranges::advance(current, n, distance_apriori_sentinel(range.size()));
-  assert(current.base().base() == expected.coordinate);
-  assert(result == expected.result);
-
-  if constexpr (std::random_access_iterator<It>) {
-    assert(current.stride_count() == 0 || current.stride_count() == 1);
-    assert(current.stride_displacement() == current.stride_count());
-  } else {
-    assert(current.stride_count() == (n - result));
-    assert(current.stride_displacement() == (n - result));
+  // Count operations
+  if constexpr (Count) {
+    auto it = stride_counting_iterator(It(first));
+    auto sent = sentinel_wrapper(stride_counting_iterator(It(last)));
+    (void)std::ranges::advance(it, n, sent);
+    // We don't have a sized sentinel, so we have to increment one-by-one
+    // regardless of the iterator category.
+    assert(it.stride_count() == M);
+    assert(it.stride_displacement() == M);
   }
 }
 
-template <std::random_access_iterator It>
-constexpr void check_backward_sized_sentinel(std::ptr
diff _t n, expected_t expected, range_t& range) {
+template <typename It>
+constexpr void check_forward_sized_sentinel(int* first, int* last, std::iter_
diff erence_t<It> n, int* expected) {
   using Difference = std::iter_
diff erence_t<It>;
-  auto current = stride_counting_iterator(It(range.end()));
-  Difference const result = std::ranges::advance(current, -n, stride_counting_iterator(It(range.begin())));
-  assert(current.base().base() == expected.coordinate);
-  assert(result == expected.result);
+  Difference const size = (last - first);
+  Difference const M = (expected - first); // expected travel distance
 
-  assert(current.stride_count() == 0 || current.stride_count() == 1);
-  assert(current.stride_displacement() == current.stride_count());
-}
+  {
+    It it(first);
+    auto sent = distance_apriori_sentinel(size);
+    std::same_as<Difference> auto result = std::ranges::advance(it, n, sent);
+    assert(result == n - M);
+    assert(base(it) == expected);
+  }
 
-template <std::input_or_output_iterator It>
-constexpr void check_forward(std::ptr
diff _t n, expected_t expected, range_t& range) {
-  using Difference = std::iter_
diff erence_t<It>;
-  auto current = stride_counting_iterator(It(range.begin()));
-  Difference const result = std::ranges::advance(current, n, sentinel_wrapper(It(range.end())));
-  assert(current.base().base() == expected.coordinate);
-  assert(result == expected.result);
-  assert(current.stride_count() == n - result);
+  // Count operations
+  {
+    auto it = stride_counting_iterator(It(first));
+    auto sent = distance_apriori_sentinel(size);
+    (void)std::ranges::advance(it, n, sent);
+    if constexpr (std::random_access_iterator<It>) {
+      assert(it.stride_count() <= 1);
+      assert(it.stride_displacement() <= 1);
+    } else {
+      assert(it.stride_count() == M);
+      assert(it.stride_displacement() == M);
+    }
+  }
 }
 
-template <std::bidirectional_iterator It>
-constexpr void check_backward(std::ptr
diff _t n, expected_t expected, range_t& range) {
+template <typename It>
+constexpr void check_backward(int* first, int* last, std::iter_
diff erence_t<It> n, int* expected) {
+  static_assert(std::random_access_iterator<It>, "This test doesn't support non random access iterators");
   using Difference = std::iter_
diff erence_t<It>;
-  auto current = stride_counting_iterator(It(range.end()));
-  Difference const result = std::ranges::advance(current, -n, stride_counting_iterator(It(range.begin())));
-  assert(current.base().base() == expected.coordinate);
-  assert(result == expected.result);
-  assert(current.stride_count() == n + result);
-  assert(current.stride_count() == -current.stride_displacement());
+  Difference const M = (expected - last); // expected travel distance (which is negative)
+
+  {
+    It it(last);
+    It sent(first);
+    std::same_as<Difference> auto result = std::ranges::advance(it, n, sent);
+    assert(result == n - M);
+    assert(base(it) == expected);
+  }
+
+  // Count operations
+  {
+    auto it = stride_counting_iterator(It(last));
+    auto sent = stride_counting_iterator(It(first));
+    (void)std::ranges::advance(it, n, sent);
+    assert(it.stride_count() <= 1);
+    assert(it.stride_displacement() <= 1);
+  }
 }
 
 struct iota_iterator {
@@ -95,40 +117,42 @@ static_assert(std::bidirectional_iterator<iota_iterator>);
 static_assert(std::sized_sentinel_for<iota_iterator, iota_iterator>);
 
 constexpr bool test() {
-  auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-  check_forward_sized_sentinel<cpp17_input_iterator<range_t::const_iterator> >(1, {range.begin() + 1, 0}, range);
-  // cpp20_input_iterator not copyable, so is omitted
-  check_forward_sized_sentinel<forward_iterator<range_t::const_iterator> >(3, {range.begin() + 3, 0}, range);
-  check_forward_sized_sentinel<bidirectional_iterator<range_t::const_iterator> >(4, {range.begin() + 4, 0}, range);
-  check_forward_sized_sentinel<random_access_iterator<range_t::const_iterator> >(5, {range.begin() + 5, 0}, range);
-  check_forward_sized_sentinel<contiguous_iterator<range_t::const_iterator> >(6, {range.begin() + 6, 0}, range);
-
-  // bidirectional_iterator omitted because the `n < 0` case requires `same_as<I, S>`
-  check_backward_sized_sentinel<random_access_iterator<range_t::const_iterator> >(5, {range.begin() + 5, 0}, range);
-  check_backward_sized_sentinel<contiguous_iterator<range_t::const_iterator> >(6, {range.begin() + 4, 0}, range);
-
-  // distance == range.size()
-  check_forward_sized_sentinel<forward_iterator<range_t::const_iterator> >(10, {range.end(), 0}, range);
-  check_backward_sized_sentinel<random_access_iterator<range_t::const_iterator> >(10, {range.begin(), 0}, range);
-
-  // distance > range.size()
-  check_forward_sized_sentinel<forward_iterator<range_t::const_iterator> >(1000, {range.end(), 990}, range);
-  check_backward_sized_sentinel<random_access_iterator<range_t::const_iterator> >(1000, {range.begin(), -990}, range);
-
-  check_forward<cpp17_input_iterator<range_t::const_iterator> >(1, {range.begin() + 1, 0}, range);
-  check_forward<forward_iterator<range_t::const_iterator> >(3, {range.begin() + 3, 0}, range);
-  check_forward<bidirectional_iterator<range_t::const_iterator> >(4, {range.begin() + 4, 0}, range);
-  check_forward<random_access_iterator<range_t::const_iterator> >(5, {range.begin() + 5, 0}, range);
-  check_forward<contiguous_iterator<range_t::const_iterator> >(6, {range.begin() + 6, 0}, range);
-  check_backward<bidirectional_iterator<range_t::const_iterator> >(8, {range.begin() + 2, 0}, range);
-
-  // distance == range.size()
-  check_forward<forward_iterator<range_t::const_iterator> >(10, {range.end(), 0}, range);
-  check_backward<bidirectional_iterator<range_t::const_iterator> >(10, {range.begin(), 0}, range);
-
-  // distance > range.size()
-  check_forward<forward_iterator<range_t::const_iterator> >(1000, {range.end(), 990}, range);
-  check_backward<bidirectional_iterator<range_t::const_iterator> >(1000, {range.begin(), -990}, range);
+  int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+  for (int size = 0; size != 10; ++size) {
+    for (int n = 0; n != 20; ++n) {
+
+      {
+        int* expected = n > size ? range + size : range + n;
+        check_forward<false, cpp17_input_iterator<int*>>(  range, range+size, n, expected);
+        check_forward<false, cpp20_input_iterator<int*>>(  range, range+size, n, expected);
+        check_forward<true,  forward_iterator<int*>>(      range, range+size, n, expected);
+        check_forward<true,  bidirectional_iterator<int*>>(range, range+size, n, expected);
+        check_forward<true,  random_access_iterator<int*>>(range, range+size, n, expected);
+        check_forward<true,  contiguous_iterator<int*>>(   range, range+size, n, expected);
+        check_forward<true,  int*>(                        range, range+size, n, expected);
+
+        check_forward_sized_sentinel<cpp17_input_iterator<int*>>(  range, range+size, n, expected);
+        check_forward_sized_sentinel<cpp20_input_iterator<int*>>(  range, range+size, n, expected);
+        check_forward_sized_sentinel<forward_iterator<int*>>(      range, range+size, n, expected);
+        check_forward_sized_sentinel<bidirectional_iterator<int*>>(range, range+size, n, expected);
+        check_forward_sized_sentinel<random_access_iterator<int*>>(range, range+size, n, expected);
+        check_forward_sized_sentinel<contiguous_iterator<int*>>(   range, range+size, n, expected);
+        check_forward_sized_sentinel<int*>(                        range, range+size, n, expected);
+      }
+
+      {
+        // Note that we can only test ranges::advance with a negative n for iterators that
+        // are sized sentinels for themselves, because ranges::advance is UB otherwise.
+        // In particular, that excludes bidirectional_iterators since those are not sized sentinels.
+        // TODO: Enable these tests once we fix the bug in ranges::advance
+        // int* expected = n > size ? range : range + size - n;
+        // check_backward<random_access_iterator<int*>>(range, range+size, -n, expected);
+        // check_backward<contiguous_iterator<int*>>(   range, range+size, -n, expected);
+        // check_backward<int*>(                        range, range+size, -n, expected);
+      }
+    }
+  }
 
   // regression-test that INT_MIN doesn't cause any undefined behavior
   {

diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp
index 71ead2f9f962..0760572faccb 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp
@@ -13,112 +13,108 @@
 
 #include <iterator>
 
-#include <array>
 #include <cassert>
 #include <cstddef>
 
-#include "test_iterators.h"
 #include "../types.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+
+template <bool Count, class It>
+constexpr void check_assignable(int* first, int* last, int* expected) {
+  {
+    It it(first);
+    auto sent = assignable_sentinel(It(last));
+    std::ranges::advance(it, sent);
+    ASSERT_SAME_TYPE(decltype(std::ranges::advance(it, sent)), void);
+    assert(base(it) == expected);
+  }
 
-using range_t = std::array<int, 10>;
-
-template <class It, class Sent = It>
-constexpr void check_assignable_case() {
-  auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-
-  for (std::ptr
diff _t n = 0; n != 9; ++n) {
-    {
-      It first(range.begin());
-      Sent last(It(range.begin() + n));
-      std::ranges::advance(first, last);
-      assert(base(first) == range.begin() + n);
-    }
-
-    // Count operations
-    if constexpr (std::is_same_v<It, Sent>) {
-      stride_counting_iterator<It> first(It(range.begin()));
-      stride_counting_iterator<It> last(It(range.begin() + n));
-      std::ranges::advance(first, last);
-      assert(first.base().base() == range.begin() + n);
-      assert(first.stride_count() == 0); // because we got here by assigning from last, not by incrementing
-    }
+  // Count operations
+  if constexpr (Count) {
+    auto it = stride_counting_iterator(It(first));
+    auto sent = assignable_sentinel(stride_counting_iterator(It(last)));
+    std::ranges::advance(it, sent);
+    assert(base(it.base()) == expected);
+    assert(it.stride_count() == 0); // because we got here by assigning from last, not by incrementing
   }
 }
 
-template <class It>
-constexpr void check_sized_sentinel_case() {
-  auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+template <bool Count, class It>
+constexpr void check_sized_sentinel(int* first, int* last, int* expected) {
+  auto size = (last - first);
 
-  for (std::ptr
diff _t n = 0; n != 9; ++n) {
-    {
-      It first(range.begin());
-      distance_apriori_sentinel last(n);
-      std::ranges::advance(first, last);
-      assert(base(first) == range.begin() + n);
-    }
+  {
+    It it(first);
+    auto sent = distance_apriori_sentinel(size);
+    std::ranges::advance(it, sent);
+    ASSERT_SAME_TYPE(decltype(std::ranges::advance(it, sent)), void);
+    assert(base(it) == expected);
+  }
 
-    // Count operations
-    {
-      stride_counting_iterator<It> first(It(range.begin()));
-      distance_apriori_sentinel last(n);
-      std::ranges::advance(first, last);
-
-      assert(first.base().base() == range.begin() + n);
-      if constexpr (std::random_access_iterator<It>) {
-        assert(first.stride_count() == 1);
-        assert(first.stride_displacement() == 1);
-      } else {
-        assert(first.stride_count() == n);
-        assert(first.stride_displacement() == n);
-      }
+  // Count operations
+  if constexpr (Count) {
+    auto it = stride_counting_iterator(It(first));
+    auto sent = distance_apriori_sentinel(size);
+    std::ranges::advance(it, sent);
+    if constexpr (std::random_access_iterator<It>) {
+      assert(it.stride_count() == 1);
+    } else {
+      assert(it.stride_count() == size);
     }
   }
 }
 
-template <class It>
-constexpr void check_sentinel_case() {
-  auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+template <bool Count, class It>
+constexpr void check_sentinel(int* first, int* last, int* expected) {
+  auto size = (last - first);
 
-  for (std::ptr
diff _t n = 0; n != 9; ++n) {
-    {
-      It first(range.begin());
-      sentinel_wrapper<It> last(It(range.begin() + n));
-      std::ranges::advance(first, last);
-      assert(base(first) == range.begin() + n);
-    }
+  {
+    It it(first);
+    auto sent = sentinel_wrapper(It(last));
+    std::ranges::advance(it, sent);
+    ASSERT_SAME_TYPE(decltype(std::ranges::advance(it, sent)), void);
+    assert(base(it) == expected);
+  }
 
-    // Count operations
-    {
-      stride_counting_iterator<It> first(It(range.begin()));
-      sentinel_wrapper<It> last(It(range.begin() + n));
-      std::ranges::advance(first, last);
-      assert(first.base() == last);
-      assert(first.stride_count() == n);
-    }
+  // Count operations
+  if constexpr (Count) {
+    auto it = stride_counting_iterator(It(first));
+    auto sent = sentinel_wrapper(stride_counting_iterator(It(last)));
+    std::ranges::advance(it, sent);
+    assert(it.stride_count() == size);
   }
 }
 
 constexpr bool test() {
-  using It = range_t::const_iterator;
-  check_assignable_case<cpp17_input_iterator<It>, sentinel_wrapper<cpp17_input_iterator<It>>>();
-  check_assignable_case<forward_iterator<It>>();
-  check_assignable_case<bidirectional_iterator<It>>();
-  check_assignable_case<random_access_iterator<It>>();
-  check_assignable_case<contiguous_iterator<It>>();
-
-  check_sized_sentinel_case<cpp17_input_iterator<It>>();
-  check_sized_sentinel_case<cpp20_input_iterator<It>>();
-  check_sized_sentinel_case<forward_iterator<It>>();
-  check_sized_sentinel_case<bidirectional_iterator<It>>();
-  check_sized_sentinel_case<random_access_iterator<It>>();
-  check_sized_sentinel_case<contiguous_iterator<It>>();
-
-  check_sentinel_case<cpp17_input_iterator<It>>();
-  // cpp20_input_iterator not copyable, so is omitted
-  check_sentinel_case<forward_iterator<It>>();
-  check_sentinel_case<bidirectional_iterator<It>>();
-  check_sentinel_case<random_access_iterator<It>>();
-  check_sentinel_case<contiguous_iterator<It>>();
+  int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+  for (int n = 0; n != 10; ++n) {
+    check_assignable<false, cpp17_input_iterator<int*>>(  range, range+n, range+n);
+    check_assignable<false, cpp20_input_iterator<int*>>(  range, range+n, range+n);
+    check_assignable<true,  forward_iterator<int*>>(      range, range+n, range+n);
+    check_assignable<true,  bidirectional_iterator<int*>>(range, range+n, range+n);
+    check_assignable<true,  random_access_iterator<int*>>(range, range+n, range+n);
+    check_assignable<true,  contiguous_iterator<int*>>(   range, range+n, range+n);
+    check_assignable<true,  int*>(                        range, range+n, range+n);
+
+    check_sized_sentinel<false, cpp17_input_iterator<int*>>(  range, range+n, range+n);
+    check_sized_sentinel<false, cpp20_input_iterator<int*>>(  range, range+n, range+n);
+    check_sized_sentinel<true,  forward_iterator<int*>>(      range, range+n, range+n);
+    check_sized_sentinel<true,  bidirectional_iterator<int*>>(range, range+n, range+n);
+    check_sized_sentinel<true,  random_access_iterator<int*>>(range, range+n, range+n);
+    check_sized_sentinel<true,  contiguous_iterator<int*>>(   range, range+n, range+n);
+    check_sized_sentinel<true,  int*>(                        range, range+n, range+n);
+
+    check_sentinel<false, cpp17_input_iterator<int*>>(  range, range+n, range+n);
+    check_sentinel<false, cpp20_input_iterator<int*>>(  range, range+n, range+n);
+    check_sentinel<true,  forward_iterator<int*>>(      range, range+n, range+n);
+    check_sentinel<true,  bidirectional_iterator<int*>>(range, range+n, range+n);
+    check_sentinel<true,  random_access_iterator<int*>>(range, range+n, range+n);
+    check_sentinel<true,  contiguous_iterator<int*>>(   range, range+n, range+n);
+    check_sentinel<true,  int*>(                        range, range+n, range+n);
+  }
+
   return true;
 }
 

diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator.pass.cpp
index 5c8c0ae84196..972b410cf2f2 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator.pass.cpp
@@ -12,29 +12,34 @@
 // ranges::next(it)
 
 #include <iterator>
+
 #include <cassert>
+#include <concepts>
+#include <utility>
 
 #include "test_iterators.h"
 
 template <class It>
-constexpr void check() {
-  int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-  assert(&*std::ranges::next(It(&range[0])) == &range[1]);
-  assert(&*std::ranges::next(It(&range[1])) == &range[2]);
-  assert(&*std::ranges::next(It(&range[2])) == &range[3]);
-  assert(&*std::ranges::next(It(&range[3])) == &range[4]);
-  assert(&*std::ranges::next(It(&range[4])) == &range[5]);
-  assert(&*std::ranges::next(It(&range[5])) == &range[6]);
+constexpr void check(int* first, int* expected) {
+  It it(first);
+  std::same_as<It> auto result = std::ranges::next(std::move(it));
+  assert(base(result) == expected);
 }
 
 constexpr bool test() {
-  check<cpp17_input_iterator<int*>>();
-  check<cpp20_input_iterator<int*>>();
-  check<forward_iterator<int*>>();
-  check<bidirectional_iterator<int*>>();
-  check<random_access_iterator<int*>>();
-  check<contiguous_iterator<int*>>();
-  check<output_iterator<int*>>();
+  int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+  for (int n = 0; n != 9; ++n) {
+    check<cpp17_input_iterator<int*>>(  range+n, range+n+1);
+    check<cpp20_input_iterator<int*>>(  range+n, range+n+1);
+    check<forward_iterator<int*>>(      range+n, range+n+1);
+    check<bidirectional_iterator<int*>>(range+n, range+n+1);
+    check<random_access_iterator<int*>>(range+n, range+n+1);
+    check<contiguous_iterator<int*>>(   range+n, range+n+1);
+    check<output_iterator<int*>>(       range+n, range+n+1);
+    check<int*>(                        range+n, range+n+1);
+  }
+
   return true;
 }
 

diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_count.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_count.pass.cpp
index 447d3a9d3d45..0bc400dde1b4 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_count.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_count.pass.cpp
@@ -14,55 +14,41 @@
 #include <iterator>
 
 #include <cassert>
+#include <concepts>
 #include <utility>
 
 #include "test_iterators.h"
 
-template <std::input_or_output_iterator It>
-constexpr void check_steps(It it, std::ptr
diff _t n, int const* expected) {
-  {
-    It result = std::ranges::next(std::move(it), n);
-    assert(&*result == expected);
-  }
-
-  // Count the number of operations
-  {
-    stride_counting_iterator strided_it(std::move(it));
-    stride_counting_iterator result = std::ranges::next(std::move(strided_it), n);
-    assert(&*result == expected);
-    if constexpr (std::random_access_iterator<It>) {
-      assert(result.stride_count() == 1); // uses += exactly once
-      assert(result.stride_displacement() == 1);
-    } else {
-      auto const abs_n = n < 0 ? -n : n;
-      assert(result.stride_count() == abs_n);
-      assert(result.stride_displacement() == n);
-    }
-  }
+template <typename It>
+constexpr void check(int* first, std::iter_
diff erence_t<It> n, int* expected) {
+  It it(first);
+  std::same_as<It> auto result = std::ranges::next(std::move(it), n);
+  assert(base(result) == expected);
 }
 
 constexpr bool test() {
   int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
 
-  check_steps(cpp17_input_iterator(&range[0]), 1, &range[1]);
-  check_steps(cpp20_input_iterator(&range[6]), 2, &range[8]);
-  check_steps(forward_iterator(&range[0]), 3, &range[3]);
-  check_steps(bidirectional_iterator(&range[2]), 6, &range[8]);
-  check_steps(random_access_iterator(&range[3]), 4, &range[7]);
-  check_steps(contiguous_iterator(&range[0]), 5, &range[5]);
-  check_steps(output_iterator(&range[0]), 6, &range[6]);
+  // Check next() forward
+  for (int n = 0; n != 10; ++n) {
+    check<cpp17_input_iterator<int*>>(  range, n, range+n);
+    check<cpp20_input_iterator<int*>>(  range, n, range+n);
+    check<forward_iterator<int*>>(      range, n, range+n);
+    check<bidirectional_iterator<int*>>(range, n, range+n);
+    check<random_access_iterator<int*>>(range, n, range+n);
+    check<contiguous_iterator<int*>>(   range, n, range+n);
+    check<int*>(                        range, n, range+n);
+    check<output_iterator<int*> >(      range, n, range+n);
+  }
 
-  check_steps(cpp17_input_iterator(&range[0]), 0, &range[0]);
-  check_steps(cpp20_input_iterator(&range[6]), 0, &range[6]);
-  check_steps(forward_iterator(&range[0]), 0, &range[0]);
-  check_steps(bidirectional_iterator(&range[2]), 0, &range[2]);
-  check_steps(random_access_iterator(&range[3]), 0, &range[3]);
-  check_steps(contiguous_iterator(&range[0]), 0, &range[0]);
-  check_steps(output_iterator(&range[0]), 0, &range[0]);
+  // Check next() backward
+  for (int n = 0; n != 10; ++n) {
+    check<bidirectional_iterator<int*>>(range+9, -n, range+9 - n);
+    check<random_access_iterator<int*>>(range+9, -n, range+9 - n);
+    check<contiguous_iterator<int*>>(   range+9, -n, range+9 - n);
+    check<int*>(                        range+9, -n, range+9 - n);
+  }
 
-  check_steps(bidirectional_iterator(&range[8]), -5, &range[3]);
-  check_steps(random_access_iterator(&range[6]), -3, &range[3]);
-  check_steps(contiguous_iterator(&range[4]), -1, &range[3]);
   return true;
 }
 

diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_count_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_count_sentinel.pass.cpp
index 3c0e9d89ea64..5cfbbf3c5a15 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_count_sentinel.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_count_sentinel.pass.cpp
@@ -12,56 +12,38 @@
 // ranges::next(it, n, bound)
 
 #include <iterator>
+
 #include <cassert>
-#include <type_traits>
+#include <concepts>
+#include <utility>
 
 #include "test_iterators.h"
 
-template <class It, class Sent = It>
-constexpr void check(It it, std::ptr
diff _t n, Sent last) {
-  {
-    It result = std::ranges::next(it, n, last);
-    assert(result == last);
-  }
+template <typename It>
+constexpr void check(int* first, int* last, std::iter_
diff erence_t<It> n, int* expected) {
+  It it(first);
+  auto sent = sentinel_wrapper(It(last));
 
-  // Count the number of operations
-  if constexpr (std::is_same_v<It, Sent>) {
-    stride_counting_iterator<It> strided_it(it);
-    stride_counting_iterator<It> strided_last(last);
-    stride_counting_iterator<It> result = std::ranges::next(strided_it, n, strided_last);
-    assert(result == strided_last);
-    if constexpr (std::random_access_iterator<It>) {
-      if (n == 0 || n >= (last - it)) {
-        assert(result.stride_count() == 0); // uses the assign-from-sentinel codepath
-      } else {
-        assert(result.stride_count() == 1); // uses += exactly once
-      }
-    } else {
-      std::ptr
diff _t const abs_n = n < 0 ? -n : n;
-      assert(result.stride_count() == abs_n);
-      assert(result.stride_displacement() == n);
-    }
-  }
+  std::same_as<It> auto result = std::ranges::next(std::move(it), n, sent);
+  assert(base(result) == expected);
 }
 
 constexpr bool test() {
   int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
 
-  check(cpp17_input_iterator(&range[0]), 1, sentinel_wrapper(cpp17_input_iterator(&range[1])));
-  check(forward_iterator(&range[0]), 2, forward_iterator(&range[2]));
-  check(bidirectional_iterator(&range[2]), 6, bidirectional_iterator(&range[8]));
-  check(random_access_iterator(&range[3]), 2, random_access_iterator(&range[5]));
-  check(contiguous_iterator(&range[0]), 5, contiguous_iterator(&range[5]));
-
-  check(cpp17_input_iterator(&range[0]), 0, sentinel_wrapper(cpp17_input_iterator(&range[0])));
-  check(forward_iterator(&range[0]), 0, forward_iterator(&range[0]));
-  check(bidirectional_iterator(&range[2]), 0, bidirectional_iterator(&range[2]));
-  check(random_access_iterator(&range[3]), 0, random_access_iterator(&range[3]));
-  check(contiguous_iterator(&range[0]), 0, contiguous_iterator(&range[0]));
+  for (int size = 0; size != 10; ++size) {
+    for (int n = 0; n != 20; ++n) {
+      int* expected = n > size ? range + size : range + n;
+      check<cpp17_input_iterator<int*>>(  range, range+size, n, expected);
+      check<cpp20_input_iterator<int*>>(  range, range+size, n, expected);
+      check<forward_iterator<int*>>(      range, range+size, n, expected);
+      check<bidirectional_iterator<int*>>(range, range+size, n, expected);
+      check<random_access_iterator<int*>>(range, range+size, n, expected);
+      check<contiguous_iterator<int*>>(   range, range+size, n, expected);
+      check<int*>(                        range, range+size, n, expected);
+    }
+  }
 
-  check(bidirectional_iterator(&range[6]), -1, bidirectional_iterator(&range[5]));
-  check(random_access_iterator(&range[7]), -2, random_access_iterator(&range[5]));
-  check(contiguous_iterator(&range[8]), -3, contiguous_iterator(&range[5]));
   return true;
 }
 

diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_sentinel.pass.cpp
index 950fd77401a7..633a6bd7b6de 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_sentinel.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_sentinel.pass.cpp
@@ -13,101 +13,68 @@
 
 #include <iterator>
 
-#include <array>
 #include <cassert>
+#include <concepts>
 #include <utility>
 
-#include "test_iterators.h"
 #include "../types.h"
+#include "test_iterators.h"
 
-using range_t = std::array<int, 10>;
-
-template <bool Count, typename It>
-constexpr void check_assignable(int* it, int* last, int const* expected) {
-  {
-    It result = std::ranges::next(It(it), assignable_sentinel(It(last)));
-    assert(base(result) == expected);
-  }
-
-  // Count operations
-  if constexpr (Count) {
-    auto strided_it = stride_counting_iterator(It(it));
-    auto strided_last = assignable_sentinel(stride_counting_iterator(It(last)));
-    stride_counting_iterator<It> result = std::ranges::next(std::move(strided_it), std::move(strided_last));
-    assert(base(result.base()) == expected);
-    assert(result.stride_count() == 0); // because we got here by assigning from last, not by incrementing
-  }
+template <typename It>
+constexpr void check_assignable(int* first, int* last, int* expected) {
+  It it(first);
+  auto sent = assignable_sentinel(It(last));
+  It result = std::ranges::next(std::move(it), sent);
+  assert(base(result) == expected);
 }
 
 template <typename It>
-constexpr void check_sized_sentinel(int* it, int* last, int const* expected) {
-  auto n = (last - it);
-
-  {
-    auto sent = distance_apriori_sentinel(n);
-    auto result = std::ranges::next(It(it), sent);
-    assert(base(result) == expected);
-  }
+constexpr void check_sized_sentinel(int* first, int* last, int* expected) {
+  auto size = (last - first);
 
-  // Count operations
-  {
-    auto strided_it = stride_counting_iterator(It(it));
-    auto sent = distance_apriori_sentinel(n);
-    auto result = std::ranges::next(std::move(strided_it), sent);
-    assert(base(result.base()) == expected);
-
-    if constexpr (std::random_access_iterator<It>) {
-      assert(result.stride_count() == 1); // should have used exactly one +=
-      assert(result.stride_displacement() == 1);
-    } else {
-      assert(result.stride_count() == n);
-      assert(result.stride_displacement() == n);
-    }
-  }
+  It it(first);
+  auto sent = distance_apriori_sentinel(size);
+  std::same_as<It> auto result = std::ranges::next(std::move(it), sent);
+  assert(base(result) == expected);
 }
 
-template <bool Count, typename It>
-constexpr void check_sentinel(int* it, int* last, int const* expected) {
-  auto n = (last - it);
-
-  {
-    auto sent = sentinel_wrapper(It(last));
-    It result = std::ranges::next(It(it), sent);
-    assert(base(result) == expected);
-  }
-
-  // Count operations
-  if constexpr (Count) {
-    auto strided_it = stride_counting_iterator(It(it));
-    auto sent = sentinel_wrapper(stride_counting_iterator(It(last)));
-    stride_counting_iterator result = std::ranges::next(std::move(strided_it), sent);
-    assert(base(result.base()) == expected);
-    assert(result.stride_count() == n); // must have used ++ until it hit the sentinel
-  }
+template <typename It>
+constexpr void check_sentinel(int* first, int* last, int* expected) {
+  It it(first);
+  auto sent = sentinel_wrapper(It(last));
+  std::same_as<It> auto result = std::ranges::next(std::move(it), sent);
+  assert(base(result) == expected);
 }
 
 constexpr bool test() {
   int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
 
-  check_assignable<false, cpp17_input_iterator<int*>>(  &range[0], &range[2], &range[2]);
-  check_assignable<true,  forward_iterator<int*>>(      &range[0], &range[3], &range[3]);
-  check_assignable<true,  bidirectional_iterator<int*>>(&range[0], &range[4], &range[4]);
-  check_assignable<true,  random_access_iterator<int*>>(&range[0], &range[5], &range[5]);
-  check_assignable<true,  contiguous_iterator<int*>>(   &range[0], &range[6], &range[6]);
-
-  check_sized_sentinel<cpp17_input_iterator<int*>>(  &range[0], &range[7], &range[7]);
-  check_sized_sentinel<cpp20_input_iterator<int*>>(  &range[0], &range[6], &range[6]);
-  check_sized_sentinel<forward_iterator<int*>>(      &range[0], &range[5], &range[5]);
-  check_sized_sentinel<bidirectional_iterator<int*>>(&range[0], &range[4], &range[4]);
-  check_sized_sentinel<random_access_iterator<int*>>(&range[0], &range[3], &range[3]);
-  check_sized_sentinel<contiguous_iterator<int*>>(   &range[0], &range[2], &range[2]);
+  for (int n = 0; n != 10; ++n) {
+    check_assignable<cpp17_input_iterator<int*>>(  range, range+n, range+n);
+    check_assignable<cpp20_input_iterator<int*>>(  range, range+n, range+n);
+    check_assignable<forward_iterator<int*>>(      range, range+n, range+n);
+    check_assignable<bidirectional_iterator<int*>>(range, range+n, range+n);
+    check_assignable<random_access_iterator<int*>>(range, range+n, range+n);
+    check_assignable<contiguous_iterator<int*>>(   range, range+n, range+n);
+    check_assignable<int*>(                        range, range+n, range+n);
+
+    check_sized_sentinel<cpp17_input_iterator<int*>>(  range, range+n, range+n);
+    check_sized_sentinel<cpp20_input_iterator<int*>>(  range, range+n, range+n);
+    check_sized_sentinel<forward_iterator<int*>>(      range, range+n, range+n);
+    check_sized_sentinel<bidirectional_iterator<int*>>(range, range+n, range+n);
+    check_sized_sentinel<random_access_iterator<int*>>(range, range+n, range+n);
+    check_sized_sentinel<contiguous_iterator<int*>>(   range, range+n, range+n);
+    check_sized_sentinel<int*>(                        range, range+n, range+n);
+
+    check_sentinel<cpp17_input_iterator<int*>>(  range, range+n, range+n);
+    check_sentinel<cpp20_input_iterator<int*>>(  range, range+n, range+n);
+    check_sentinel<forward_iterator<int*>>(      range, range+n, range+n);
+    check_sentinel<bidirectional_iterator<int*>>(range, range+n, range+n);
+    check_sentinel<random_access_iterator<int*>>(range, range+n, range+n);
+    check_sentinel<contiguous_iterator<int*>>(   range, range+n, range+n);
+    check_sentinel<int*>(                        range, range+n, range+n);
+  }
 
-  check_sentinel<false, cpp17_input_iterator<int*>>(  &range[0], &range[1], &range[1]);
-  // cpp20_input_iterator not copyable, so is omitted
-  check_sentinel<true,  forward_iterator<int*>>(      &range[0], &range[3], &range[3]);
-  check_sentinel<true,  bidirectional_iterator<int*>>(&range[0], &range[4], &range[4]);
-  check_sentinel<true,  random_access_iterator<int*>>(&range[0], &range[5], &range[5]);
-  check_sentinel<true,  contiguous_iterator<int*>>(   &range[0], &range[6], &range[6]);
   return true;
 }
 

diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator.pass.cpp
index c7d1d8be2c5b..334b674adeb7 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator.pass.cpp
@@ -17,23 +17,26 @@
 #include "test_iterators.h"
 
 template <class It>
-constexpr void check() {
-  int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-  assert(std::ranges::prev(It(&range[1])) == It(&range[0]));
-  assert(std::ranges::prev(It(&range[4])) == It(&range[3]));
-  assert(std::ranges::prev(It(&range[5])) == It(&range[4]));
-  assert(std::ranges::prev(It(&range[6])) == It(&range[5]));
-  assert(std::ranges::prev(It(&range[10])) == It(&range[9]));
+constexpr void check(int* first, int* expected) {
+  It it(first);
+  std::same_as<It> auto result = std::ranges::prev(std::move(it));
+  assert(base(result) == expected);
 }
 
 constexpr bool test() {
-  check<bidirectional_iterator<int*>>();
-  check<random_access_iterator<int*>>();
-  check<contiguous_iterator<int*>>();
-  check<int*>();
+  int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+  for (int n = 1; n != 10; ++n) {
+    check<bidirectional_iterator<int*>>(range+n, range+n-1);
+    check<random_access_iterator<int*>>(range+n, range+n-1);
+    check<contiguous_iterator<int*>>(   range+n, range+n-1);
+    check<int*>(                        range+n, range+n-1);
+  }
+
   return true;
 }
 
+
 int main(int, char**) {
   test();
   static_assert(test());

diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator_count.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator_count.pass.cpp
index cb6d2aac2c07..2a4cee39fdbc 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator_count.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator_count.pass.cpp
@@ -12,40 +12,39 @@
 // ranges::prev(it, n)
 
 #include <iterator>
+
 #include <cassert>
+#include <concepts>
 #include <utility>
 
 #include "test_iterators.h"
 
-template <std::input_or_output_iterator It>
-constexpr void check(It it, std::ptr
diff _t n, int const* expected) {
-  stride_counting_iterator result = std::ranges::prev(stride_counting_iterator(std::move(it)), n);
-  assert(result.base().base() == expected);
-
-  if constexpr (std::random_access_iterator<It>) {
-    assert(result.stride_count() <= 1);
-    // we can't say anything about the stride displacement, cause we could be using -= or +=.
-  } else {
-    std::ptr
diff _t const abs_n = n < 0 ? -n : n;
-    assert(result.stride_count() == abs_n);
-    assert(result.stride_displacement() == -n);
-  }
+template <typename It>
+constexpr void check(int* first, std::iter_
diff erence_t<It> n, int* expected) {
+  It it(first);
+  std::same_as<It> auto result = std::ranges::prev(std::move(it), n);
+  assert(base(result) == expected);
 }
 
 constexpr bool test() {
   int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
 
-  check(bidirectional_iterator(&range[8]), 6, &range[2]);
-  check(random_access_iterator(&range[7]), 4, &range[3]);
-  check(contiguous_iterator(&range[5]), 5, &range[0]);
+  // Check prev() forward
+  for (int n = 0; n != 10; ++n) {
+    check<bidirectional_iterator<int*>>(range+n, n, range);
+    check<random_access_iterator<int*>>(range+n, n, range);
+    check<contiguous_iterator<int*>>(   range+n, n, range);
+    check<int*>(                        range+n, n, range);
+  }
 
-  check(bidirectional_iterator(&range[2]), 0, &range[2]);
-  check(random_access_iterator(&range[3]), 0, &range[3]);
-  check(contiguous_iterator(&range[0]), 0, &range[0]);
+  // Check prev() backward
+  for (int n = 0; n != 10; ++n) {
+    check<bidirectional_iterator<int*>>(range, -n, range+n);
+    check<random_access_iterator<int*>>(range, -n, range+n);
+    check<contiguous_iterator<int*>>(   range, -n, range+n);
+    check<int*>(                        range, -n, range+n);
+  }
 
-  check(bidirectional_iterator(&range[3]), -5, &range[8]);
-  check(random_access_iterator(&range[3]), -3, &range[6]);
-  check(contiguous_iterator(&range[3]), -1, &range[4]);
   return true;
 }
 

diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator_count_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator_count_sentinel.pass.cpp
index 1ca6b6f4eddb..d998f0ddb90c 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator_count_sentinel.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/iterator_count_sentinel.pass.cpp
@@ -12,52 +12,38 @@
 // ranges::prev(it, n, bound)
 
 #include <iterator>
+
 #include <cassert>
+#include <concepts>
+#include <utility>
 
 #include "test_iterators.h"
 
-template <std::bidirectional_iterator It>
-constexpr void check(It it, std::ptr
diff _t n, It last) {
-  auto abs = [](auto x) { return x < 0 ? -x : x; };
-
-  {
-    It result = std::ranges::prev(it, n, last);
-    assert(result == last);
-  }
+template <typename It>
+constexpr void check(int* first, int* last, std::iter_
diff erence_t<It> n, int* expected) {
+  It it(last);
+  It sent(first); // for std::ranges::prev, the sentinel *must* have the same type as the iterator
 
-  // Count the number of operations
-  {
-    stride_counting_iterator<It> strided_it(it);
-    stride_counting_iterator<It> strided_last(last);
-    stride_counting_iterator<It> result = std::ranges::prev(strided_it, n, strided_last);
-    assert(result == strided_last);
-    if constexpr (std::random_access_iterator<It>) {
-      if (n == 0 || abs(n) >= abs(last - it)) {
-        assert(result.stride_count() == 0); // uses the assign-from-sentinel codepath
-      } else {
-        assert(result.stride_count() == 1); // uses += exactly once
-      }
-    } else {
-      assert(result.stride_count() == abs(n));
-      assert(result.stride_displacement() == -n);
-    }
-  }
+  std::same_as<It> auto result = std::ranges::prev(std::move(it), n, std::move(sent));
+  assert(base(result) == expected);
 }
 
+// TODO: Re-enable once we fix the bug in ranges::advance
 constexpr bool test() {
+#if 0
   int range[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
 
-  check(bidirectional_iterator(&range[8]), 6, bidirectional_iterator(&range[2]));
-  check(random_access_iterator(&range[5]), 2, random_access_iterator(&range[3]));
-  check(contiguous_iterator(&range[5]), 5, contiguous_iterator(&range[0]));
-
-  check(bidirectional_iterator(&range[2]), 0, bidirectional_iterator(&range[2]));
-  check(random_access_iterator(&range[3]), 0, random_access_iterator(&range[3]));
-  check(contiguous_iterator(&range[0]), 0, contiguous_iterator(&range[0]));
+  for (int size = 0; size != 10; ++size) {
+    for (int n = 0; n != 20; ++n) {
+      int* expected = n > size ? range : range + size - n;
+      check<bidirectional_iterator<int*>>(range, range+size, n, expected);
+      check<random_access_iterator<int*>>(range, range+size, n, expected);
+      check<contiguous_iterator<int*>>(   range, range+size, n, expected);
+      check<int*>(                        range, range+size, n, expected);
+    }
+  }
+#endif
 
-  check(bidirectional_iterator(&range[5]), -1, bidirectional_iterator(&range[6]));
-  check(random_access_iterator(&range[5]), -2, random_access_iterator(&range[7]));
-  check(contiguous_iterator(&range[5]), -3, contiguous_iterator(&range[8]));
   return true;
 }
 

diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/types.h b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/types.h
index 71704c973451..433731e5dd68 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/types.h
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/types.h
@@ -14,6 +14,8 @@
 #include <iterator>
 #include <utility>
 
+#include "test_iterators.h" // for the fallthrough base() function
+
 class distance_apriori_sentinel {
 public:
   distance_apriori_sentinel() = default;


        


More information about the libcxx-commits mailing list