[libcxx-commits] [libcxx] [libc++] `std::ranges::advance`: avoid unneeded bounds checks when advancing iterator (PR #84126)
Jan Kokemüller via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Mar 5 22:59:08 PST 2024
https://github.com/jiixyj created https://github.com/llvm/llvm-project/pull/84126
Currently, the bounds check in `std::ranges::advance(it, n, s)` is done _before_ `n` is checked. This results in one extra, unneeded bounds check.
Thus, `std::ranges::advance(it, 1, s)` currently is _not_ simply equivalent to:
```c++
if (it != s) {
++it;
}
```
This difference in behavior matters when the check involves some "expensive" logic. For example, the `==` operator of `std::istreambuf_iterator` may actually have to read the underlying `streambuf`.
Swapping around the checks in the `while` results in the expected behavior.
>From dc039616cee1453a38729a4f2f6adc03fd93549c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Wed, 6 Mar 2024 07:49:25 +0100
Subject: [PATCH] skip unneeded checks against '__bound_sentinel' when
advancing iterator
---
libcxx/include/__iterator/advance.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__iterator/advance.h b/libcxx/include/__iterator/advance.h
index 7959bdeae32643..296db1aaab6526 100644
--- a/libcxx/include/__iterator/advance.h
+++ b/libcxx/include/__iterator/advance.h
@@ -170,14 +170,14 @@ struct __fn {
} else {
// Otherwise, if `n` is non-negative, while `bool(i != bound_sentinel)` is true, increments `i` but at
// most `n` times.
- while (__i != __bound_sentinel && __n > 0) {
+ while (__n > 0 && __i != __bound_sentinel) {
++__i;
--__n;
}
// Otherwise, while `bool(i != bound_sentinel)` is true, decrements `i` but at most `-n` times.
if constexpr (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>) {
- while (__i != __bound_sentinel && __n < 0) {
+ while (__n < 0 && __i != __bound_sentinel) {
--__i;
++__n;
}
More information about the libcxx-commits
mailing list