]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Fix complexity of drop_view::begin() const [PR112641]
authorPatrick Palka <ppalka@redhat.com>
Tue, 29 Oct 2024 13:26:19 +0000 (09:26 -0400)
committerPatrick Palka <ppalka@redhat.com>
Tue, 27 May 2025 20:47:33 +0000 (16:47 -0400)
Views are required to have a amortized O(1) begin(), but our drop_view's
const begin overload is O(n) for non-common ranges with a non-sized
sentinel.  This patch reimplements it so that it's O(1) always.  See
also LWG 4009.

PR libstdc++/112641

libstdc++-v3/ChangeLog:

* include/std/ranges (drop_view::begin): Reimplement const
overload so that it's O(1) always.
* testsuite/std/ranges/adaptors/drop.cc (test10): New test.

Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
(cherry picked from commit 7f622ee83fbbcf4a4ca70e020db8a0ce4b556b61)

libstdc++-v3/include/std/ranges
libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc

index 2735f1613dd1bf18c4774e231c7a4987fa7e1cbb..bdb60ecf7059b9b9668102a9f2f5bdb69b59118e 100644 (file)
@@ -2530,8 +2530,8 @@ namespace views::__adaptor
       begin() const
        requires random_access_range<const _Vp> && sized_range<const _Vp>
       {
-       return ranges::next(ranges::begin(_M_base), _M_count,
-                           ranges::end(_M_base));
+       return ranges::begin(_M_base) + ranges::min(ranges::distance(_M_base),
+                                                   _M_count);
       }
 
       constexpr auto
index 2c4047dbaa380ac8086e2491fcef84e2301c36a5..15827410227a1e7a2ec0da04e5410edc2d5645ad 100644 (file)
@@ -275,6 +275,17 @@ test09()
   static_assert(!requires { views::all | drop; });
 }
 
+constexpr bool
+test10()
+{
+  // PR libstdc++/112641 - drop_view::begin const may have O(n) complexity
+  const auto s = ranges::subrange(views::iota(size_t(1)), size_t(-1));
+  const auto r = ranges::drop_view(s, s.size() - 1);
+  const auto b = r.begin(); // time out
+  VERIFY( *b == size_t(-1) );
+  return true;
+}
+
 int
 main()
 {
@@ -287,4 +298,5 @@ main()
   test07();
   test08();
   test09();
+  static_assert(test10());
 }