[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