Skip to content

Commit d05ab11

Browse files
authored
[libc++] Remove redundant and somewhat confusing assertions around advance() (#133276)
The std::advance function has a clear precondition that it can only be called with a negative distance when a bidirectional iterator is used. However, prev() and next() don't have such preconditions explicitly, they inherit it from calling advance(). This patch removes assertions in prev() and next() that were duplicates of similar ones in advance(), and removes a copy-pasted comment that was trying to justify the use of _LIBCPP_ASSERT_PEDANTIC but IMO is creating confusion with little benefit.
1 parent 60b43ef commit d05ab11

File tree

5 files changed

+8
-21
lines changed

5 files changed

+8
-21
lines changed

libcxx/include/__iterator/advance.h

+6-8
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ template < class _InputIter,
6565
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void advance(_InputIter& __i, _Distance __orig_n) {
6666
typedef typename iterator_traits<_InputIter>::difference_type _Difference;
6767
_Difference __n = static_cast<_Difference>(std::__convert_to_integral(__orig_n));
68-
// Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation.
69-
_LIBCPP_ASSERT_PEDANTIC(__n >= 0 || __has_bidirectional_iterator_category<_InputIter>::value,
68+
_LIBCPP_ASSERT_PEDANTIC(__has_bidirectional_iterator_category<_InputIter>::value || __n >= 0,
7069
"Attempt to advance(it, n) with negative n on a non-bidirectional iterator");
7170
std::__advance(__i, __n, typename iterator_traits<_InputIter>::iterator_category());
7271
}
@@ -98,9 +97,8 @@ struct __advance {
9897
// Preconditions: If `I` does not model `bidirectional_iterator`, `n` is not negative.
9998
template <input_or_output_iterator _Ip>
10099
_LIBCPP_HIDE_FROM_ABI constexpr void operator()(_Ip& __i, iter_difference_t<_Ip> __n) const {
101-
// Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation.
102-
_LIBCPP_ASSERT_PEDANTIC(
103-
__n >= 0 || bidirectional_iterator<_Ip>, "If `n < 0`, then `bidirectional_iterator<I>` must be true.");
100+
_LIBCPP_ASSERT_PEDANTIC(bidirectional_iterator<_Ip> || __n >= 0,
101+
"ranges::advance: Can only pass a negative `n` with a bidirectional_iterator.");
104102

105103
// If `I` models `random_access_iterator`, equivalent to `i += n`.
106104
if constexpr (random_access_iterator<_Ip>) {
@@ -149,9 +147,9 @@ struct __advance {
149147
template <input_or_output_iterator _Ip, sentinel_for<_Ip> _Sp>
150148
_LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Ip>
151149
operator()(_Ip& __i, iter_difference_t<_Ip> __n, _Sp __bound_sentinel) const {
152-
// Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation.
153-
_LIBCPP_ASSERT_PEDANTIC((__n >= 0) || (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>),
154-
"If `n < 0`, then `bidirectional_iterator<I> && same_as<I, S>` must be true.");
150+
_LIBCPP_ASSERT_PEDANTIC(
151+
(bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>) || (__n >= 0),
152+
"ranges::advance: Can only pass a negative `n` with a bidirectional_iterator coming from a common_range.");
155153
// If `S` and `I` model `sized_sentinel_for<S, I>`:
156154
if constexpr (sized_sentinel_for<_Sp, _Ip>) {
157155
// If |n| >= |bound_sentinel - i|, equivalent to `ranges::advance(i, bound_sentinel)`.

libcxx/include/__iterator/next.h

-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#ifndef _LIBCPP___ITERATOR_NEXT_H
1111
#define _LIBCPP___ITERATOR_NEXT_H
1212

13-
#include <__assert>
1413
#include <__config>
1514
#include <__iterator/advance.h>
1615
#include <__iterator/concepts.h>
@@ -27,11 +26,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2726
template <class _InputIter, __enable_if_t<__has_input_iterator_category<_InputIter>::value, int> = 0>
2827
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _InputIter
2928
next(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) {
30-
// Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation.
31-
// Note that this check duplicates the similar check in `std::advance`.
32-
_LIBCPP_ASSERT_PEDANTIC(__n >= 0 || __has_bidirectional_iterator_category<_InputIter>::value,
33-
"Attempt to next(it, n) with negative n on a non-bidirectional iterator");
34-
3529
std::advance(__x, __n);
3630
return __x;
3731
}

libcxx/include/__iterator/prev.h

-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#ifndef _LIBCPP___ITERATOR_PREV_H
1111
#define _LIBCPP___ITERATOR_PREV_H
1212

13-
#include <__assert>
1413
#include <__config>
1514
#include <__iterator/advance.h>
1615
#include <__iterator/concepts.h>
@@ -31,10 +30,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3130
template <class _InputIter, __enable_if_t<__has_input_iterator_category<_InputIter>::value, int> = 0>
3231
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _InputIter
3332
prev(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n) {
34-
// Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation.
35-
// Note that this check duplicates the similar check in `std::advance`.
36-
_LIBCPP_ASSERT_PEDANTIC(__n <= 0 || __has_bidirectional_iterator_category<_InputIter>::value,
37-
"Attempt to prev(it, n) with a positive n on a non-bidirectional iterator");
3833
std::advance(__x, -__n);
3934
return __x;
4035
}

libcxx/test/libcxx/iterators/assert.next.pass.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ int main(int, char**) {
2525
forward_iterator<int *> it(a+1);
2626
(void)std::next(it, 1); // should work fine
2727
(void)std::next(it, 0); // should work fine
28-
TEST_LIBCPP_ASSERT_FAILURE(std::next(it, -1), "Attempt to next(it, n) with negative n on a non-bidirectional iterator");
28+
TEST_LIBCPP_ASSERT_FAILURE(std::next(it, -1), "Attempt to advance(it, n) with negative n on a non-bidirectional iterator");
2929

3030
return 0;
3131
}

libcxx/test/libcxx/iterators/assert.prev.pass.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ int main(int, char**) {
3131
forward_iterator<int *> it(a+1);
3232
(void)std::prev(it, -1); // should work fine
3333
(void)std::prev(it, 0); // should work fine
34-
TEST_LIBCPP_ASSERT_FAILURE(std::prev(it, 1), "Attempt to prev(it, n) with a positive n on a non-bidirectional iterator");
34+
TEST_LIBCPP_ASSERT_FAILURE(std::prev(it, 1), "Attempt to advance(it, n) with negative n on a non-bidirectional iterator");
3535

3636
return 0;
3737
}

0 commit comments

Comments
 (0)