diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/check_round_trip.h b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/check_round_trip.h deleted file mode 100644 --- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/check_round_trip.h +++ /dev/null @@ -1,31 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -#ifndef LIBCXX_TEST_CHECK_ROUND_TRIP_H -#define LIBCXX_TEST_CHECK_ROUND_TRIP_H - -#include "test_iterators.h" - -template -constexpr void check_round_trip(stride_counting_iterator const& i, std::ptrdiff_t const n) { - auto const distance = n < 0 ? -n : n; - assert(i.stride_count() == distance); - assert(i.stride_displacement() == n); -} - -template -constexpr void check_round_trip(stride_counting_iterator const& i, std::ptrdiff_t const n) { - assert(i.stride_count() <= 1); - assert(i.stride_displacement() == n < 0 ? -1 : 1); -} - -template -constexpr bool operator==(output_iterator const& x, output_iterator const& y) { - return x.base() == y.base(); -} - -#endif // LIBCXX_TEST_CHECK_ROUND_TRIP_H diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/constraints.compile.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/constraints.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/constraints.compile.pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// ranges::next +// Make sure we're SFINAE-friendly when the template argument constraints are not met. + +#include + +#include +#include +#include + +template +concept has_ranges_next = requires (Args ...args) { + { std::ranges::next(std::forward(args)...) }; +}; + +using It = std::unique_ptr; +static_assert(!has_ranges_next); +static_assert(!has_ranges_next); +static_assert(!has_ranges_next); +static_assert(!has_ranges_next); + +// Test the test +static_assert(has_ranges_next); diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/constraints.verify.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/constraints.verify.cpp deleted file mode 100644 --- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/constraints.verify.cpp +++ /dev/null @@ -1,27 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: libcpp-no-concepts -// UNSUPPORTED: gcc-10 - -// ranges::next - -#include - -#include - -#include "test_iterators.h" - -void proper_constraints() { - auto p = std::unique_ptr(); - std::ranges::next(p); // expected-error {{no matching function for call}} - std::ranges::next(p, p); // expected-error {{no matching function for call}} - std::ranges::next(p, 5); // expected-error {{no matching function for call}} - std::ranges::next(p, 7); // expected-error {{no matching function for call}} -} 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 --- 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 @@ -10,19 +10,18 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: gcc-10 -// ranges::next(first, n) +// ranges::next(first) #include #include #include -#include "check_round_trip.h" #include "test_iterators.h" using range_t = std::array; -constexpr bool check_iterator() { +constexpr bool test() { constexpr auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; assert(std::ranges::next(cpp17_input_iterator(&range[0])) == cpp17_input_iterator(&range[1])); assert(std::ranges::next(cpp20_input_iterator(&range[1])).base() == &range[2]); @@ -35,7 +34,7 @@ } int main(int, char**) { - static_assert(check_iterator()); - check_iterator(); + static_assert(test()); + test(); return 0; } 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 --- 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 @@ -10,52 +10,59 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: gcc-10 -// ranges::next(first, n) +// ranges::next(it, n) #include #include #include +#include -#include "check_round_trip.h" #include "test_iterators.h" using range_t = std::array; template -constexpr void iterator_count_impl(I first, std::ptrdiff_t const n, range_t::const_iterator const expected) { +constexpr void check_steps(I first, std::ptrdiff_t const n, range_t::const_iterator const expected) { auto result = std::ranges::next(stride_counting_iterator(std::move(first)), n); - assert(std::move(result).base().base() == expected); - check_round_trip(result, n); + assert(result.base().base() == expected); + if constexpr (std::random_access_iterator) { + assert(result.stride_count() <= 1); + // we can't say anything about the stride displacement, cause we could be using -= or +=. + } else { + auto const distance = n < 0 ? -n : n; + assert(result.stride_count() == distance); + assert(result.stride_displacement() == n); + } } -constexpr bool check_iterator_count() { +constexpr bool test() { constexpr auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - iterator_count_impl(cpp17_input_iterator(&range[0]), 1, &range[1]); - iterator_count_impl(cpp20_input_iterator(&range[6]), 2, &range[8]); - iterator_count_impl(forward_iterator(&range[0]), 3, &range[3]); - iterator_count_impl(bidirectional_iterator(&range[2]), 6, &range[8]); - iterator_count_impl(random_access_iterator(&range[3]), 4, &range[7]); - iterator_count_impl(contiguous_iterator(&range[0]), 5, &range[5]); - iterator_count_impl(output_iterator(&range[0]), 6, &range[6]); - - iterator_count_impl(cpp17_input_iterator(&range[0]), 0, &range[0]); - iterator_count_impl(cpp20_input_iterator(&range[6]), 0, &range[6]); - iterator_count_impl(forward_iterator(&range[0]), 0, &range[0]); - iterator_count_impl(bidirectional_iterator(&range[2]), 0, &range[2]); - iterator_count_impl(random_access_iterator(&range[3]), 0, &range[3]); - iterator_count_impl(contiguous_iterator(&range[0]), 0, &range[0]); - iterator_count_impl(output_iterator(&range[0]), 0, &range[0]); - - iterator_count_impl(bidirectional_iterator(&range[8]), -5, &range[3]); - iterator_count_impl(random_access_iterator(&range[6]), -3, &range[3]); - iterator_count_impl(contiguous_iterator(&range[4]), -1, &range[3]); + 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_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_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; } int main(int, char**) { - static_assert(check_iterator_count()); - check_iterator_count(); + static_assert(test()); + test(); return 0; } 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 --- 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 @@ -10,48 +10,52 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: gcc-10 -// ranges::next +// ranges::next(it, n, bound) #include #include #include -#include "check_round_trip.h" #include "test_iterators.h" template -constexpr void check_iterator_count_sentinel_impl(I first, std::ptrdiff_t const steps, I const last) { - auto result = std::ranges::next(stride_counting_iterator(first), steps, stride_counting_iterator(last)); - assert(result == last); - check_round_trip(result, steps); +constexpr void check_steps(I first, std::ptrdiff_t n, I last) { + auto result = std::ranges::next(stride_counting_iterator(first), n, stride_counting_iterator(last)); + assert(result.base() == last); + if constexpr (std::random_access_iterator) { + assert(result.stride_count() <= 1); + // we can't say anything about the stride displacement, cause we could be using -= or +=. + } else { + auto const distance = n < 0 ? -n : n; + assert(result.stride_count() == distance); + assert(result.stride_displacement() == n); + } } -constexpr bool check_iterator_count_sentinel() { +constexpr bool test() { constexpr auto range = std::array{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - check_iterator_count_sentinel_impl(cpp17_input_iterator(&range[0]), 1, cpp17_input_iterator(&range[1])); - check_iterator_count_sentinel_impl(forward_iterator(&range[0]), 2, forward_iterator(&range[2])); - check_iterator_count_sentinel_impl(bidirectional_iterator(&range[2]), 6, bidirectional_iterator(&range[8])); - check_iterator_count_sentinel_impl(random_access_iterator(&range[3]), 2, random_access_iterator(&range[5])); - check_iterator_count_sentinel_impl(contiguous_iterator(&range[0]), 5, contiguous_iterator(&range[5])); - check_iterator_count_sentinel_impl(output_iterator(&range[3]), 2, output_iterator(&range[5])); - - check_iterator_count_sentinel_impl(cpp17_input_iterator(&range[0]), 0, cpp17_input_iterator(&range[0])); - check_iterator_count_sentinel_impl(forward_iterator(&range[0]), 0, forward_iterator(&range[0])); - check_iterator_count_sentinel_impl(bidirectional_iterator(&range[2]), 0, bidirectional_iterator(&range[2])); - check_iterator_count_sentinel_impl(random_access_iterator(&range[3]), 0, random_access_iterator(&range[3])); - check_iterator_count_sentinel_impl(contiguous_iterator(&range[0]), 0, contiguous_iterator(&range[0])); - check_iterator_count_sentinel_impl(output_iterator(&range[3]), 0, output_iterator(&range[3])); - - check_iterator_count_sentinel_impl(bidirectional_iterator(&range[6]), -1, bidirectional_iterator(&range[5])); - check_iterator_count_sentinel_impl(random_access_iterator(&range[7]), -2, random_access_iterator(&range[5])); - check_iterator_count_sentinel_impl(contiguous_iterator(&range[8]), -3, contiguous_iterator(&range[5])); + check_steps(cpp17_input_iterator(&range[0]), 1, cpp17_input_iterator(&range[1])); + check_steps(forward_iterator(&range[0]), 2, forward_iterator(&range[2])); + check_steps(bidirectional_iterator(&range[2]), 6, bidirectional_iterator(&range[8])); + check_steps(random_access_iterator(&range[3]), 2, random_access_iterator(&range[5])); + check_steps(contiguous_iterator(&range[0]), 5, contiguous_iterator(&range[5])); + + check_steps(cpp17_input_iterator(&range[0]), 0, cpp17_input_iterator(&range[0])); + check_steps(forward_iterator(&range[0]), 0, forward_iterator(&range[0])); + check_steps(bidirectional_iterator(&range[2]), 0, bidirectional_iterator(&range[2])); + check_steps(random_access_iterator(&range[3]), 0, random_access_iterator(&range[3])); + check_steps(contiguous_iterator(&range[0]), 0, contiguous_iterator(&range[0])); + + check_steps(bidirectional_iterator(&range[6]), -1, bidirectional_iterator(&range[5])); + check_steps(random_access_iterator(&range[7]), -2, random_access_iterator(&range[5])); + check_steps(contiguous_iterator(&range[8]), -3, contiguous_iterator(&range[5])); return true; } int main(int, char**) { - static_assert(check_iterator_count_sentinel()); - assert(check_iterator_count_sentinel()); + static_assert(test()); + assert(test()); return 0; } 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 --- 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 @@ -10,14 +10,14 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: gcc-10 -// ranges::next +// ranges::next(it, bound) #include #include #include +#include -#include "check_round_trip.h" #include "test_iterators.h" using range_t = std::array; @@ -49,27 +49,38 @@ template constexpr void check_assignable_case(std::ptrdiff_t const n) { auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - auto result = - std::ranges::next(stride_counting_iterator(I(range.begin())), stride_counting_iterator(I(range.begin() + n))); + auto first = stride_counting_iterator(I(range.begin())); + auto last = stride_counting_iterator(I(range.begin() + n)); + auto result = std::ranges::next(std::move(first), std::move(last)); assert(result.base().base() == range.begin() + n); - assert(result.stride_count() == 0); // always zero, so don't use `check_round_trip` + assert(result.stride_count() == 0); } template constexpr void check_sized_sentinel_case(std::ptrdiff_t const n) { auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - auto result = std::ranges::next(stride_counting_iterator(I(range.begin())), distance_apriori_sentinel(n)); - assert(std::move(result).base().base() == range.begin() + n); - check_round_trip(result, n); + auto first = stride_counting_iterator(I(range.begin())); + auto last = distance_apriori_sentinel(n); + auto result = std::ranges::next(std::move(first), std::move(last)); + assert(result.base().base() == range.begin() + n); + + if constexpr (std::random_access_iterator) { + assert(result.stride_count() == 1); + assert(result.stride_displacement() == 1); + } else { + assert(result.stride_count() == n); + assert(result.stride_displacement() == n); + } } template constexpr void check_sentinel_case(std::ptrdiff_t const n) { auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - auto const last = I(range.begin() + n); - auto result = std::ranges::next(stride_counting_iterator(I(range.begin())), sentinel_wrapper(last)); - assert(std::move(result).base() == last); - assert(result.stride_count() == n); // always `n`, so don't use `check_round_trip` + auto first = stride_counting_iterator(I(range.begin())); + auto const last = sentinel_wrapper(I(range.begin() + n)); + auto result = std::ranges::next(std::move(first), std::move(last)); + assert(result.base() == last); + assert(result.stride_count() == n); } constexpr bool check_iterator_sentinel() { @@ -78,7 +89,6 @@ check_assignable_case >(4); check_assignable_case >(5); check_assignable_case >(6); - check_assignable_case >(7); check_sized_sentinel_case >(7); check_sized_sentinel_case >(6); @@ -86,7 +96,6 @@ check_sized_sentinel_case >(4); check_sized_sentinel_case >(3); check_sized_sentinel_case >(2); - check_sized_sentinel_case >(1); check_sentinel_case >(1); // cpp20_input_iterator not copyable, so is omitted @@ -94,7 +103,6 @@ check_sentinel_case >(4); check_sentinel_case >(5); check_sentinel_case >(6); - check_sentinel_case >(7); return true; } diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/check_round_trip.h b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/check_round_trip.h deleted file mode 100644 --- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/check_round_trip.h +++ /dev/null @@ -1,26 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -#ifndef LIBCXX_TEST_PREV_CHECK_ROUND_TRIP_H -#define LIBCXX_TEST_PREV_CHECK_ROUND_TRIP_H - -#include "test_iterators.h" - -template -constexpr void check_round_trip(stride_counting_iterator const& i, std::ptrdiff_t const n) { - auto const distance = n < 0 ? -n : n; - assert(i.stride_count() == distance); - assert(i.stride_displacement() == -n); -} - -template -constexpr void check_round_trip(stride_counting_iterator const& i, std::ptrdiff_t const n) { - assert(i.stride_count() <= 1); - assert(i.stride_displacement() == n < 0 ? -1 : 1); -} - -#endif // LIBCXX_TEST_PREV_CHECK_ROUND_TRIP_H diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/constraints.verify.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/constraints.compile.pass.cpp rename from libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/constraints.verify.cpp rename to libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/constraints.compile.pass.cpp --- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/constraints.verify.cpp +++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.prev/constraints.compile.pass.cpp @@ -11,16 +11,23 @@ // UNSUPPORTED: gcc-10 // ranges::prev +// Make sure we're SFINAE-friendly when the template argument constraints are not met. #include -#include - +#include +#include #include "test_iterators.h" -void proper_constraints() { - auto a = std::array{0, 1, 2}; - (void)std::ranges::prev(forward_iterator(a.begin())); // expected-error {{no matching function for call}} - (void)std::ranges::prev(forward_iterator(a.begin()), 5); // expected-error {{no matching function for call}} - (void)std::ranges::prev(forward_iterator(a.begin()), 7); // expected-error {{no matching function for call}} -} +template +concept has_ranges_prev = requires (Args ...args) { + { std::ranges::prev(std::forward(args)...) }; +}; + +using It = forward_iterator; +static_assert(!has_ranges_prev); +static_assert(!has_ranges_prev); +static_assert(!has_ranges_prev); + +// Test the test +static_assert(has_ranges_prev); 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 --- 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,10 +17,9 @@ #include #include -#include "check_round_trip.h" #include "test_iterators.h" -constexpr bool check_iterator() { +constexpr bool test() { constexpr auto range = std::array{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; assert(std::ranges::prev(bidirectional_iterator(&range[4])) == bidirectional_iterator(&range[3])); assert(std::ranges::prev(random_access_iterator(&range[5])) == random_access_iterator(&range[4])); @@ -29,7 +28,7 @@ } int main(int, char**) { - static_assert(check_iterator()); - check_iterator(); + static_assert(test()); + test(); return 0; } 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 --- 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 @@ -16,37 +16,45 @@ #include #include +#include -#include "check_round_trip.h" #include "test_iterators.h" using range_t = std::array; template -constexpr void iterator_count_impl(I first, std::ptrdiff_t const n, range_t::const_iterator const expected) { +constexpr void check_steps(I first, std::ptrdiff_t const n, range_t::const_iterator const expected) { auto result = std::ranges::prev(stride_counting_iterator(std::move(first)), n); - assert(std::move(result).base().base() == expected); - check_round_trip(result, n); + assert(result.base().base() == expected); + + if constexpr (std::random_access_iterator) { + assert(result.stride_count() <= 1); + // we can't say anything about the stride displacement, cause we could be using -= or +=. + } else { + auto const distance = n < 0 ? -n : n; + assert(result.stride_count() == distance); + assert(result.stride_displacement() == -n); + } } -constexpr bool check_iterator_count() { +constexpr bool test() { constexpr auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - iterator_count_impl(bidirectional_iterator(&range[8]), 6, &range[2]); - iterator_count_impl(random_access_iterator(&range[7]), 4, &range[3]); - iterator_count_impl(contiguous_iterator(&range[5]), 5, &range[0]); + check_steps(bidirectional_iterator(&range[8]), 6, &range[2]); + check_steps(random_access_iterator(&range[7]), 4, &range[3]); + check_steps(contiguous_iterator(&range[5]), 5, &range[0]); - iterator_count_impl(bidirectional_iterator(&range[2]), 0, &range[2]); - iterator_count_impl(random_access_iterator(&range[3]), 0, &range[3]); - iterator_count_impl(contiguous_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]); - iterator_count_impl(bidirectional_iterator(&range[3]), -5, &range[8]); - iterator_count_impl(random_access_iterator(&range[3]), -3, &range[6]); - iterator_count_impl(contiguous_iterator(&range[3]), -1, &range[4]); + check_steps(bidirectional_iterator(&range[3]), -5, &range[8]); + check_steps(random_access_iterator(&range[3]), -3, &range[6]); + check_steps(contiguous_iterator(&range[3]), -1, &range[4]); return true; } int main(int, char**) { - static_assert(check_iterator_count()); - check_iterator_count(); + static_assert(test()); + test(); return 0; } 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 --- 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 @@ -17,35 +17,42 @@ #include #include -#include "check_round_trip.h" #include "test_iterators.h" template -constexpr void check_iterator_count_sentinel_impl(I first, std::ptrdiff_t const steps, I const last) { - auto result = std::ranges::prev(stride_counting_iterator(first), steps, stride_counting_iterator(last)); +constexpr void check_steps(I first, std::ptrdiff_t const n, I const last) { + auto result = std::ranges::prev(stride_counting_iterator(first), n, stride_counting_iterator(last)); assert(result == last); - check_round_trip(result, steps); + + if constexpr (std::random_access_iterator) { + assert(result.stride_count() <= 1); + // we can't say anything about the stride displacement, cause we could be using -= or +=. + } else { + auto const distance = n < 0 ? -n : n; + assert(result.stride_count() == distance); + assert(result.stride_displacement() == -n); + } } -constexpr bool check_iterator_count_sentinel() { +constexpr bool test() { constexpr auto range = std::array{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - check_iterator_count_sentinel_impl(bidirectional_iterator(&range[8]), 6, bidirectional_iterator(&range[2])); - check_iterator_count_sentinel_impl(random_access_iterator(&range[5]), 2, random_access_iterator(&range[3])); - check_iterator_count_sentinel_impl(contiguous_iterator(&range[5]), 5, contiguous_iterator(&range[0])); + check_steps(bidirectional_iterator(&range[8]), 6, bidirectional_iterator(&range[2])); + check_steps(random_access_iterator(&range[5]), 2, random_access_iterator(&range[3])); + check_steps(contiguous_iterator(&range[5]), 5, contiguous_iterator(&range[0])); - check_iterator_count_sentinel_impl(bidirectional_iterator(&range[2]), 0, bidirectional_iterator(&range[2])); - check_iterator_count_sentinel_impl(random_access_iterator(&range[3]), 0, random_access_iterator(&range[3])); - check_iterator_count_sentinel_impl(contiguous_iterator(&range[0]), 0, contiguous_iterator(&range[0])); + check_steps(bidirectional_iterator(&range[2]), 0, bidirectional_iterator(&range[2])); + check_steps(random_access_iterator(&range[3]), 0, random_access_iterator(&range[3])); + check_steps(contiguous_iterator(&range[0]), 0, contiguous_iterator(&range[0])); - check_iterator_count_sentinel_impl(bidirectional_iterator(&range[5]), -1, bidirectional_iterator(&range[6])); - check_iterator_count_sentinel_impl(random_access_iterator(&range[5]), -2, random_access_iterator(&range[7])); - check_iterator_count_sentinel_impl(contiguous_iterator(&range[5]), -3, contiguous_iterator(&range[8])); + check_steps(bidirectional_iterator(&range[5]), -1, bidirectional_iterator(&range[6])); + check_steps(random_access_iterator(&range[5]), -2, random_access_iterator(&range[7])); + check_steps(contiguous_iterator(&range[5]), -3, contiguous_iterator(&range[8])); return true; } int main(int, char**) { - static_assert(check_iterator_count_sentinel()); - assert(check_iterator_count_sentinel()); + static_assert(test()); + assert(test()); return 0; } diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h --- a/libcxx/test/support/test_iterators.h +++ b/libcxx/test/support/test_iterators.h @@ -729,7 +729,7 @@ constexpr explicit stride_counting_iterator(I current) : base_(std::move(current)) {} - [[nodiscard]] constexpr I const& base() const& requires std::copyable { return base_; } + [[nodiscard]] constexpr I const& base() const& { return base_; } [[nodiscard]] constexpr I base() && { return std::move(base_); }