[libcxx-commits] [libcxx] [libc++] `std::ranges::advance`: avoid unneeded bounds checks when advancing iterator (PR #84126)
Konstantin Varlamov via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Apr 1 16:52:43 PDT 2024
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/84126 at github.com>
================
@@ -109,33 +108,13 @@ constexpr void check_backward(int* first, int* last, std::iter_difference_t<It>
auto it = stride_counting_iterator(It(last));
auto sent = stride_counting_iterator(It(first));
static_assert(std::bidirectional_iterator<stride_counting_iterator<It>>);
+ static_assert(Count == !std::sized_sentinel_for<It, It>);
(void)std::ranges::advance(it, n, sent);
- if constexpr (std::sized_sentinel_for<It, It>) {
- if (expected == first) {
- // In this case, the algorithm can just do `it = std::move(sent);`
- // instead of doing iterator arithmetic:
- // <https://eel.is/c++draft/iterators#range.iter.op.advance-4.1>
- assert(it.stride_count() == 0);
- assert(it.stride_displacement() == 0);
- } else {
- assert(it.stride_count() == 1);
- assert(it.stride_displacement() == 1);
- }
- assert(it.equals_count() == 0);
- } else {
- assert(it.stride_count() == -M);
- assert(it.stride_displacement() == M);
- if (-n > -M) {
- // We "hit" the bound, so there is one extra equality check.
- assert(it.equals_count() == -M + 1);
- } else {
- assert(it.equals_count() == -M);
- }
- // In any case, there must not be more than `-n` bounds checks.
- assert(it.equals_count() <= -n);
- }
+ assert(it.stride_count() == expected_stride_count);
----------------
var-const wrote:
Very optional: I think you could define a simple struct and use it to imitate named arguments:
```cpp
struct Expected { int stride_count; int stride_displacement; int equals_count; };
constexpr void check_backward(..., Expected expected) {
...
assert(it.stride_count() == expected.stride_count;
}
...
check_backward(..., {.stride_count = stride_count, .stride_displacement = stride_displacement, .equals_count = equals_count});
```
https://github.com/llvm/llvm-project/pull/84126
More information about the libcxx-commits
mailing list